[PYTHON] Ich habe AWS CDK ausprobiert!

Etwas lange Einführung

Über diesen Artikel

In letzter Zeit habe ich nicht viele Artikel "Ich habe es versucht" geschrieben. Dies liegt daran, dass die offiziellen Websites so umfangreich sind, dass Sie am Ende nur die offiziellen Websites verfolgen.

** Dieses Mal kannte ich AWS CDK und war tief bewegt, also werde ich es so schreiben, wie es ist. ** ** **

Was ist CDK?

Es ist ein Zitat von der offiziellen Website, aber Sie können AWS-Ressourcen in einer vertrauten Programmiersprache erstellen, ohne CloudFormation oder Teraform zu verwenden! !! ** Das ist jetzt! Es ist auch jetzt! !! ** ** **

Das AWS Cloud Development Kit (AWS CDK) ist ein Open Source-Softwareentwicklungsframework zur Modellierung und Bereitstellung von Cloud-Anwendungsressourcen unter Verwendung vertrauter Programmiersprachen.

https://aws.amazon.com/jp/cdk/

Woher wusstest du das

In den Informationen, die die Teammitglieder während der internen technischen Akquisitionsaktivitäten zur Verfügung stellten, wurde das AWS CDK kurz erwähnt.
Zuerst kannte ich die Existenz nicht und dachte über einen Fehler im AWS SDK nach.

Ich werde nicht darauf eingehen, weil es vom Hauptthema abweicht, aber die Informationen, die fließen, sind sehr nützlich! Ich kann es nur empfehlen. https://tomomano.gitlab.io/intro-aws/

## Was in diesem Artikel zu erwähnen CDK hat viele Beispiele. https://github.com/aws-samples/aws-cdk-examples

Dieses Mal werde ich den Prozess des Erstellens einer neuen VPC mit Python und der Bereitstellung von ALB und EC2 verfolgen. https://github.com/aws-samples/aws-cdk-examples/tree/master/python/new-vpc-alb-asg-mysql Es wäre schön, wenn das Beispiel so wie es ist in Ihre Umgebung gegossen werden könnte, aber ich denke nicht, dass dies der Fall ist. (Da die CIDR von VPC bereits zugewiesen ist und kollidieren kann) ** Mit welchem Teil des Beispiels kann man also praktisch spielen? Ich möchte hauptsächlich aus dieser Perspektive erklären. ** ** **

Endlich das Hauptthema

Ich werde hier endlich auf das Hauptthema eingehen.

Voraussetzungen

Natürlich benötigen Sie ein AWS-Konto. (Dieser Bereich wird wie erwartet weggelassen) Und verschiedene Installationen sind erforderlich. Da Sie durch Abschluss des Workshops eine Umgebung erstellen können, ist nur Hello, CDK! Erforderlich. Wir empfehlen Ihnen daher dringend, dies zu tun. https://cdkworkshop.com/

Lassen Sie uns zuerst das Beispiel mit den minimalen Änderungen gießen! (1. Runde)

Klonen Sie als grobe Prozedur das oben erwähnte Beispiel und verwenden Sie Pythons neues-vpc-alb-asg-mysql. Lassen Sie uns das Beispiel ein wenig ändern und es zuerst einfüllen. (Dies ist die erste Runde. Es wird eine zweite Runde später geben.)

clone Ich habe vergessen, es zu schreiben, aber ich benutze Ubuntu 18.04. Für Lernmaterial graben wir Unterverzeichnisse für jedes Thema in einem Verzeichnis namens Praxis. Klonen Sie es also unter ~ / Practice / cdk /. (Bitte ändern Sie diesen Bereich auf gut)

$ git clone https://github.com/aws-samples/aws-cdk-examples.git

Infolgedessen wird Pythons neuer Untergebener "vpc-alb-asg-mysql" wie folgt.

$ tree
.
├── app.py
├── cdk.json
├── cdk_vpc_ec2
│   ├── cdk_ec2_stack.py
│   ├── cdk_rds_stack.py
│   └── cdk_vpc_stack.py
├── img_demo_cdk_vpc.png
├── README.md
├── requirements.txt
├── setup.py
└── user_data
    └── user_data.sh

2 directories, 10 files

Dateimodifikation und -ausführung

Nehmen Sie zuerst die minimalen Änderungen vor und gießen Sie sie tatsächlich ein. Die zu ändernde Datei ist

ist. Es tut mir leid, dass es schwer zu verstehen ist, aber die japanischen Kommentare im Quellcode wurden von mir gemacht. Bitte beziehen Sie sich auf sie.

Da es lange dauern wird, wird der Inhalt der Dateiänderung reduziert.

Hier klicken für Details.
Vorher ändern

cdk_vpc_stack.py (vor dem Wechsel)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2


class CdkVpcStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # The code that defines your stack goes here

        self.vpc = ec2.Vpc(self, "VPC",
                           max_azs=2,
                           cidr="10.10.0.0/16", #CIDR ist fest geschrieben!
                           # configuration will create 3 groups in 2 AZs = 6 subnets.
                           subnet_configuration=[ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PUBLIC,
                               name="Public",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PRIVATE,
                               name="Private",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.ISOLATED,
                               name="DB",
                               cidr_mask=24
                           )
                           ],
                           # nat_gateway_provider=ec2.NatProvider.gateway(),
                           nat_gateways=2,
                           )
        core.CfnOutput(self, "Output",
                       value=self.vpc.vpc_id)

Die CIDR von VPC ist 10.10.0.0/16. Wenn dies in Ordnung ist, können Sie es so ausführen, wie es ist, aber in meinem Fall musste ich es ändern, damit ich es ändern kann. Da es nicht einfach zu verwenden ist, wenn es inline geschrieben ist, habe ich beschlossen, es als Variable auszuschneiden.

Nach der veränderung

cdk_vpc_stack.py (nach Änderung)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2


vpc_cidr = "x.x.x.x/16" #Definieren Sie die CIDR als Variable und schreiben Sie sie auf einen beliebigen Wert um.

class CdkVpcStack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # The code that defines your stack goes here

        self.vpc = ec2.Vpc(self, "VPC",
                           max_azs=2,
                           cidr=vpc_cidr,  #Geändert, um Variablen zu verwenden
                           # configuration will create 3 groups in 2 AZs = 6 subnets.
                           subnet_configuration=[ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PUBLIC,
                               name="Public",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.PRIVATE,
                               name="Private",
                               cidr_mask=24
                           ), ec2.SubnetConfiguration(
                               subnet_type=ec2.SubnetType.ISOLATED,
                               name="DB",
                               cidr_mask=24
                           )
                           ],
                           # nat_gateway_provider=ec2.NatProvider.gateway(),
                           nat_gateways=2,
                           )
        core.CfnOutput(self, "Output",
                       value=self.vpc.vpc_id)

Als nächstes kommt EC2. (Kurz gesagt, ändern Sie den Schlüsselnamen des Schlüsselpaars.)

Vorher ändern

cdk_ec2_stack.py (vor dem Wechsel)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2
import aws_cdk.aws_elasticloadbalancingv2 as elb
import aws_cdk.aws_autoscaling as autoscaling

ec2_type = "t2.micro"
key_name = "id_rsa"  # Setup key_name for EC2 instance login 
linux_ami = ec2.AmazonLinuxImage(generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX,
                                 edition=ec2.AmazonLinuxEdition.STANDARD,
                                 virtualization=ec2.AmazonLinuxVirt.HVM,
                                 storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
                                 )  # Indicate your AMI, no need a specific id in the region
with open("./user_data/user_data.sh") as f:
    user_data = f.read()


class CdkEc2Stack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, vpc, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Create Bastion
        bastion = ec2.BastionHostLinux(self, "myBastion",
                                       vpc=vpc,
                                       subnet_selection=ec2.SubnetSelection(
                                           subnet_type=ec2.SubnetType.PUBLIC),
                                       instance_name="myBastionHostLinux",
                                       instance_type=ec2.InstanceType(instance_type_identifier="t2.micro"))
        
        # Setup key_name for EC2 instance login if you don't use Session Manager
        # bastion.instance.instance.add_property_override("KeyName", key_name)

        bastion.connections.allow_from_any_ipv4(
            ec2.Port.tcp(22), "Internet access SSH")

        # Create ALB
        alb = elb.ApplicationLoadBalancer(self, "myALB",
                                          vpc=vpc,
                                          internet_facing=True,
                                          load_balancer_name="myALB"
                                          )
        alb.connections.allow_from_any_ipv4(
            ec2.Port.tcp(80), "Internet access ALB 80")
        listener = alb.add_listener("my80",
                                    port=80,
                                    open=True)

        # Create Autoscaling Group with fixed 2*EC2 hosts
        self.asg = autoscaling.AutoScalingGroup(self, "myASG",
                                                vpc=vpc,
                                                vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
                                                instance_type=ec2.InstanceType(instance_type_identifier=ec2_type),
                                                machine_image=linux_ami,
                                                key_name=key_name,
                                                user_data=ec2.UserData.custom(user_data),
                                                desired_capacity=2,
                                                min_capacity=2,
                                                max_capacity=2,
                                                # block_devices=[
                                                #     autoscaling.BlockDevice(
                                                #         device_name="/dev/xvda",
                                                #         volume=autoscaling.BlockDeviceVolume.ebs(
                                                #             volume_type=autoscaling.EbsDeviceVolumeType.GP2,
                                                #             volume_size=12,
                                                #             delete_on_termination=True
                                                #         )),
                                                #     autoscaling.BlockDevice(
                                                #         device_name="/dev/sdb",
                                                #         volume=autoscaling.BlockDeviceVolume.ebs(
                                                #             volume_size=20)
                                                #         # 20GB, with default volume_type gp2
                                                #     )
                                                # ]
                                                )

        self.asg.connections.allow_from(alb, ec2.Port.tcp(80), "ALB access 80 port of EC2 in Autoscaling Group")
        listener.add_targets("addTargetGroup",
                             port=80,
                             targets=[self.asg])

        core.CfnOutput(self, "Output",
                       value=alb.load_balancer_dns_name)

Nach der veränderung

python:python:cdk_ec2_stack.py (nach Änderung)


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2
import aws_cdk.aws_elasticloadbalancingv2 as elb
import aws_cdk.aws_autoscaling as autoscaling

ec2_type = "t2.micro"
key_name = "hogehoge" #Wechseln Sie zu dem zuvor vorbereiteten Schlüsselpaar.
linux_ami = ec2.AmazonLinuxImage(generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX,
                                 edition=ec2.AmazonLinuxEdition.STANDARD,
                                 virtualization=ec2.AmazonLinuxVirt.HVM,
                                 storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
                                 )  # Indicate your AMI, no need a specific id in the region
with open("./user_data/user_data.sh") as f:
    user_data = f.read()

#Ab diesem Zeitpunkt entfällt die Veröffentlichung.

Gießen!

Danke fürs Warten. Lassen Sie uns vorerst eine Ressource in diesem Zustand erstellen.

#Set venv.
$ cd ~/practice/cdk/aws-cdk-examples/python/new-vpc-alb-asg-mysql
$ python3 -m venv .env
$ source .env/bin/activate

#Installation abhängiger Bibliotheken
$ pip install -r requirements.txt

#Geben Sie den CDK-Befehl ein, um eine CloudFormation-Vorlage zu generieren.
$ cdk ls
cdk-vpc
cdk-ec2
cdk-rds

$ cdk synth
Successfully synthesized to /home/****/practice/cdk/aws-cdk-examples/python/new-vpc-alb-asg-mysql/cdk.out

Ein Verzeichnis mit dem Namen cdk.out wird erstellt, und darin werden CloudFormation-Vorlagen erstellt. (Übrigens war die Vorlage json ... ist es nicht yaml?)

$ cdk bootstrap

$ cdk deploy cdk-vpc #Es braucht Zeit. (das gleiche wie oben)
$ cdk deploy cdk-ec2
$ cdk deploy cdk-rds

Der CloudFormation-Stapel ist abgeschlossen, und schließlich ist die gewünschte Ressource abgeschlossen. Da nicht alle aufgelistet werden können, wird nur das Subnetz mit der Ansicht von der Verwaltungskonsole verbunden. [TBD] Fügen Sie das Bild ein.

Probleme an dieser Stelle

Diese werden in der zweiten Runde gelöst. Also habe ich es geschafft, aber ich werde die Ressource leicht löschen!

Ressource löschen

#Ich habe es in umgekehrter Reihenfolge gelöscht, als ich es gemacht habe. Es verschwand sauber. (Wie erwartet wird der CloudFormation-Stapel gelöscht.)
$ cdk destroy cdk-rds
$ cdk destroy cdk-ec2
$ cdk destroy cdk-vpc


Machen Sie eine Pause (schreiben Sie etwas unerwartet Wichtiges)

Zum Beispiel ein privates Subnetz 「cdk-vpc/VPC/PrivateSubnet1」 Sie können es mit dem Namen tun.

Sie können / (Schrägstrich) im Ressourcennamen verwenden! ?? Das war frisch Der Ort, an dem Kebab Case (-Tsunagi) und Camel Case gemischt werden, ist verspielt.

Wie wird der Ressourcenname ermittelt? Apropos (Details bedürfen der Bestätigung) 最初のcdk-vpcの部分は、app.py Da das Folgende in angegeben ist, scheint dies dadurch entschieden zu sein.

app.py (Auszug nur teilweise)


vpc_stack = CdkVpcStack(app, "cdk-vpc")
ec2_stack = CdkEc2Stack(app, "cdk-ec2",
                        vpc=vpc_stack.vpc)
rds_stack = CdkRdsStack(app, "cdk-rds",
                        vpc=vpc_stack.vpc,
                        asg_security_groups=ec2_stack.asg.connections.security_groups)

Daher möchte ich für die zweite Runde den CDK-Teil auf einen etwas signifikanteren Wert ändern. Dieses Mal (obwohl nicht sehr wichtig) werde ich akira-test-cdk- versuchen.

Lass uns in die zweite Runde gehen! !! Lass uns et al!

2. Runde

Änderungen in der zweiten Runde

Ändern Sie den Ressourcennamen in akira-test-cdk-begin

app.py


#!/usr/bin/env python3

from aws_cdk import core

from cdk_vpc_ec2.cdk_vpc_stack import CdkVpcStack
from cdk_vpc_ec2.cdk_ec2_stack import CdkEc2Stack
from cdk_vpc_ec2.cdk_rds_stack import CdkRdsStack

app = core.App()

vpc_stack = CdkVpcStack(app, "akira-test-cdk-vpc")
ec2_stack = CdkEc2Stack(app, "akira-test-cdk-ec2",
                        vpc=vpc_stack.vpc)
rds_stack = CdkRdsStack(app, "akira-test-cdk-rds",
                        vpc=vpc_stack.vpc,
                        asg_security_groups=ec2_stack.asg.connections.security_groups)

app.synth()

Weisen Sie der eingehenden IP-Adresse der Bastion & Narrow down Security Group das Schlüsselpaar zu und verwenden Sie den 8080-Port

Jedes ist ein Pseudonym, also lesen Sie es bitte, wie Sie möchten.

cdk_ec2_stack.py


from aws_cdk import core
import aws_cdk.aws_ec2 as ec2
import aws_cdk.aws_elasticloadbalancingv2 as elb
import aws_cdk.aws_autoscaling as autoscaling

ec2_type = "t2.micro"
key_name = "hogehoge" #Wechseln Sie zu dem zuvor vorbereiteten Schlüsselpaar.
linux_ami = ec2.AmazonLinuxImage(generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2, #Wechseln Sie zu Amazon Linux 2
                                 edition=ec2.AmazonLinuxEdition.STANDARD,
                                 virtualization=ec2.AmazonLinuxVirt.HVM,
                                 storage=ec2.AmazonLinuxStorage.GENERAL_PURPOSE
                                 )  # Indicate your AMI, no need a specific id in the region
with open("./user_data/user_data.sh") as f:
    user_data = f.read()


class CdkEc2Stack(core.Stack):

    def __init__(self, scope: core.Construct, id: str, vpc, **kwargs) -> None:
        super().__init__(scope, id, **kwargs)

        # Create Bastion
        bastion = ec2.BastionHostLinux(self, "myBastion",
                                       vpc=vpc,
                                       subnet_selection=ec2.SubnetSelection(
                                           subnet_type=ec2.SubnetType.PUBLIC),
                                       instance_name="myBastionHostLinux",
                                       instance_type=ec2.InstanceType(instance_type_identifier="t2.micro"))
        
        # Setup key_name for EC2 instance login if you don't use Session Manager
        #Kommentieren Sie hier aus und registrieren Sie das Schlüsselpaar
        bastion.instance.instance.add_property_override("KeyName", key_name)

        #Grenzen Sie die Quell-IP ein
        # bastion.connections.allow_from_any_ipv4(
        bastion.connections.allow_from(ec2.Peer.ipv4("x.x.x.x/32"), #Quell-IP hier!
            ec2.Port.tcp(22), "Internet access SSH")

        # Create ALB
        alb = elb.ApplicationLoadBalancer(self, "myALB",
                                          vpc=vpc,
                                          internet_facing=True,
                                          load_balancer_name="myALB"
                                          )
        alb.connections.allow_from_any_ipv4(
            ec2.Port.tcp(80), "Internet access ALB 80")
        listener = alb.add_listener("my80",
                                    port=80,
                                    open=True)

        # Create Autoscaling Group with fixed 2*EC2 hosts
        self.asg = autoscaling.AutoScalingGroup(self, "myASG",
                                                vpc=vpc,
                                                vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
                                                instance_type=ec2.InstanceType(instance_type_identifier=ec2_type),
                                                machine_image=linux_ami,
                                                key_name=key_name,
                                                user_data=ec2.UserData.custom(user_data),
                                                desired_capacity=2,
                                                min_capacity=2,
                                                max_capacity=2,
volume_type=autoscaling.EbsDeviceVolumeType.GP2,
                                                )

        self.asg.connections.allow_from(alb, ec2.Port.tcp(8080), "ALB access 8080 port of EC2 in Autoscaling Group")
        listener.add_targets("addTargetGroup",
                             port=8080, # 80 ->Wechseln Sie zu 8080
                             targets=[self.asg])

        core.CfnOutput(self, "Output",
                       value=alb.load_balancer_dns_name)


Ändern Sie user_data

user_data.sh


#!/bin/bash
sudo yum update -y
sudo yum install -y java-11-amazon-corretto-headless
sudo yum install -y maven
# sudo yum -y install httpd php
# sudo chkconfig httpd on
# sudo service httpd start

Anstatt ein RDS zu erstellen, führen wir vorerst eine DB-unabhängige Rauchtest-App aus!

Führen Sie vorerst die Spring Boot App auf EC2 aus. (Es tut mir leid, dass ich erschöpft bin und die Erklärung hier chaotisch ist ... Nun, es ist nicht das Hauptthema.)

HelloController.java


package com.example.demo;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloController {

    @GetMapping("/")
    public String hello() {
        return "Hello, Spring boot with AWS CDK";
    }
}

** Da die mit EC2 der App verknüpfte Sicherheitsgruppe nur den Zugriff von ALB akzeptiert, ist es derzeit nicht möglich, von Bastion auf EC2 der App zu ssh. Ändern Sie daher die Sicherheitsgruppe und ändern Sie sie manuell, um ssh von Bastion zu akzeptieren. ** ** **

[TODO] Die Erklärung hier ist zu kompliziert, also mache ich es ein bisschen mehr ...

#Bringen Sie das Glas mit SCP usw. zu EC2.

#anfangen
$ java -jar demo-0.0.1-SNAPSHOT.jar

#Erreichen Sie den Endpunkt als Ergebnis der Bereitstellung von ec2.

Impressionen

CloudFormation hat den Eindruck, dass es für die für die Anwendung verantwortliche Person etwas schwierig ist, eine AWS-Umgebung zu erstellen. CDK ist eine beliebte Programmiersprache, die den Eindruck erweckt, dass der Infrastrukturcode dadurch leichter zu lesen ist. Ich habe diesmal Python verwendet, wollte es aber auch in anderen Sprachen ausprobieren.

Die API-Spezifikationen finden Sie unten. https://docs.aws.amazon.com/cdk/api/latest/python/modules.html

Recommended Posts

Ich habe AWS CDK ausprobiert!
Ich habe AWS Iot ausprobiert
Ich habe versucht, AWS Chalice zu verwenden
Ich habe versucht zu kratzen
Ich habe PyQ ausprobiert
Ich habe AutoKeras ausprobiert
Ich habe es mit Papiermühle versucht
Ich habe versucht, Django-Slack
Ich habe es mit Django versucht
Ich habe es mit Spleeter versucht
Ich habe es mit cgo versucht
Ich habe versucht, parametrisiert zu verwenden
Ich habe versucht, Argparse zu verwenden
Ich habe versucht, die Detect Labels-API von AWS Rekognition zu verwenden
Ich habe versucht, Mimesis zu verwenden
Ich habe versucht, anytree zu verwenden
Ich habe versucht, Pymc auszuführen
Ich habe ARP-Spoofing ausprobiert
Ich habe versucht, aiomysql zu verwenden
Ich habe Python> autopep8 ausprobiert
Ich habe versucht, Coturn zu verwenden
Ich habe versucht, Pipenv zu verwenden
Ich habe versucht, Matplotlib zu verwenden
Ich habe versucht, "Anvil" zu verwenden.
Ich habe versucht, Hubot zu verwenden
Ich habe versucht, ESPCN zu verwenden
Ich habe PyCaret2.0 (pycaret-nightly) ausprobiert.
Ich habe versucht, openpyxl zu verwenden
Ich habe versucht, Ipython zu verwenden
Ich habe versucht zu debuggen.
Ich habe versucht, PyCaret zu verwenden
Ich habe versucht, Cron zu verwenden
Ich habe Kivys Kartenansicht ausprobiert
Ich habe versucht, ngrok zu verwenden
Ich habe versucht, face_recognition zu verwenden
Ich habe versucht, Jupyter zu verwenden
Ich habe versucht, AWS Lambda mit anderen Diensten zu verbinden
Ich habe versucht, EfficientDet zu verschieben
Ich habe versucht, Shell zu programmieren
Ich habe versucht, doctest zu verwenden
Ich habe Python> Decorator ausprobiert
Ich habe versucht, TensorFlow auszuführen
Ich habe Auto Gluon ausprobiert
Ich habe versucht, Folium zu verwenden
Ich habe versucht, jinja2 zu verwenden
Ich habe die Bayes'sche Optimierung ausprobiert!
Ich habe AWS Chalice berührt
Ich habe versucht, einen URL-Verkürzungsdienst mit AWS CDK serverlos zu machen
Ich habe versucht, Folium zu verwenden
Ich habe versucht, das Zeitfenster zu verwenden
Als ich versuchte, eine VPC mit AWS CDK zu erstellen, konnte ich es aber nicht schaffen
Ich habe eine emotionale Analyse von Amazon Comprehend mit der AWS CLI durchgeführt.
Ich habe versucht, mit AWS Lambda einen AMI zu erhalten
AWS Lambda unterstützt jetzt Python, also habe ich es versucht
[Einführung in AWS] Ich habe versucht, mit der Sprach-Text-Konvertierung zu spielen ♪
Ich habe Value Iteration Networks ausprobiert