运行 MySQL 集群支持,启用 HTTPS Spring AWS 上的启动应用程序 (EKS)

Run MySQL cluster backed, HTTPS-enabled Spring boot app on AWS (EKS)

我正在查看有关如何使用 AWS EKS(适用于 Kubernetes 的弹性容器服务)运行 我的 spring 启动、mysql 支持的应用程序的分步教程现有的 SSL 通配符证书,无法找到完整的解决方案。

该应用程序是一个标准的 Spring 启动自包含应用程序,由 MySQL 数据库支持,运行 宁在端口 8080 上。我需要 运行 它与高可用性,高冗余,包括需要处理大量写入和读取的 MySQL 数据库。

我决定使用 EKS 托管的集群,将自定义 Docker 图像保存到 AWS 自己的 ECR 私有 Docker 回购中,以对抗 EKS 托管的 MySQL 集群。并使用 AWS 颁发的 SSL 证书通过 HTTPS 进行通信。以下是我的解决方案,但我很想知道如何以不同的方式完成它

这是一个循序渐进的教程。在上一步完成之前,请不要继续。

创建 EKS 集群

按照the standard tutorial创建EKS集群。不要执行第 4 步。完成后,您应该有一个正常工作的 EKS 集群,并且您必须能够使用 kubectl 实用程序与集群通信。从命令行执行时,您应该看到工作节点和其他集群元素使用 kubectl get all --all-namespaces 命令

安装MYSQL集群

我使用 helm 按照 this tutorial 中的步骤安装了 MySQL 集群。以下是步骤

安装头盔

因为我使用 Macbook Pro 和 homebrew 我使用了 brew install kubernetes-helm 命令

部署MySQL集群

请注意,在 MySQL 集群Kubernetes (EKS) 集群 中,单词 "cluster" 指的是 2不同的东西。基本上,您正在将集群安装到集群中,就像俄罗斯套娃一样,因此您的 MySQL 集群最终 运行ning 在 EKS 集群节点上。

我使用了 this tutorial 的第二部分(忽略 kops 部分)来准备 helm 图表并安装 MySQL 集群。引用 helm 配置:

$ kubectl create serviceaccount -n kube-system tiller

serviceaccount "tiller" created

$ kubectl create clusterrolebinding tiller-crule --clusterrole=cluster-admin --serviceaccount=kube-system:tiller

clusterrolebinding.rbac.authorization.k8s.io "tiller-crule" created

$ helm init --service-account tiller --wait

$HELM_HOME has been configured at /home/presslabs/.helm.
Tiller (the Helm server-side component) has been installed into your Kubernetes Cluster.
Please note: by default, Tiller is deployed with an insecure 'allow unauthenticated users' policy.
For more information on securing your installation see: https://docs.helm.sh/using_helm/#securing-your-helm-installation
Happy Helming!

$ helm repo add presslabs https://presslabs.github.io/charts

"presslabs" has been added to your repositories

$ helm install presslabs/mysql-operator --name mysql-operator

NAME:   mysql-operator
LAST DEPLOYED: Tue Aug 14 15:50:42 2018
NAMESPACE: default
STATUS: DEPLOYED

我运行所有命令完全按照上面引用。

在创建集群之前,您需要一个包含 ROOT_PASSWORD 密钥的密钥。

创建一个名为 example-cluster-secret.yaml 的文件并将以下 YAML 代码复制到其中

apiVersion: v1
kind: Secret
metadata:
  name: my-secret
type: Opaque
data:
  # root password is required to be specified
  ROOT_PASSWORD: Zm9vYmFy

但是那是什么 ROOT_PASSWORD?事实证明这是您计划与 MySQL root 用户一起使用的 base64 编码密码。假设您想要 root/foobar(请不要实际使用 foobar)。对密码进行编码的最简单方法是使用其中一个网站,例如 https://www.base64encode.org/,它将 foobar 编码为 Zm9vYmFy

准备就绪后执行kubectl apply -f example-cluster-secret.yaml,这将创建一个新的秘密

然后您需要创建一个名为 example-cluster.yaml 的文件并将以下 YAML 代码复制到其中:

apiVersion: mysql.presslabs.org/v1alpha1
kind: MysqlCluster
metadata:
  name: my-cluster
spec:
  replicas: 2
  secretName: my-secret

请注意 secretName 如何匹配您刚刚创建的秘密名称。只要它在两个文件中都匹配,您就可以将其更改为更有意义的内容。现在 运行 kubectl apply -f example-cluster.yaml 最终创建一个 MySQL 集群。使用

进行测试
$ kubectl get mysql
NAME        AGE
my-cluster  1m

请注意,我没有按照本文其余部分所述配置备份。您无需为数据库操作而执行此操作。但是如何访问您的数据库?此时 mysql 服务已经存在,但它没有外部 IP。在我的例子中,我什至不想要,只要我的应用程序 运行 在同一个 EKS 集群上可以访问它。

但是您可以使用 kubectl 端口转发从 运行s kubectl 的开发箱访问数据库。键入此命令:kubectl port-forward services/my-cluster-mysql 8806:3306。现在您可以使用用户 root 和非编码密码 (foobar) 从 127.0.0.1:8806 访问您的数据库。在单独的命令提示符中输入:mysql -u root -h 127.0.0.1 -P 8806 -p。有了它,您还可以使用 MySQL Workbench 来管理您的数据库,只是不要忘记 运行 port-forward。当然你可以将 8806 更改为你选择的其他端口

将您的应用打包为 DOCKER 映像并部署

要将 Spring 启动应用程序部署到 EKS 集群中,您需要将其打包到 Docker 映像中并将其部署到 Docker 存储库中。让我们从 Docker 图像开始。关于这个 like this one 有很多教程,但步骤很简单:

将生成的自包含 spring 引导 jar 文件放入一个目录中,并在同一目录中创建一个确切名称为 Dockerfile 的文本文件,并向其中添加以下内容:

FROM openjdk:8-jdk-alpine
MAINTAINER me@mydomain.com
LABEL name="My Awesome Docker Image" 
# Add spring boot jar
VOLUME /tmp
ADD myapp-0.1.8.jar app.jar
EXPOSE 8080
# Database settings (maybe different in your app)
ENV RDS_USERNAME="my_user"
ENV RDS_PASSWORD="foobar"
# Other options
ENV JAVA_OPTS="-Dverknow.pypath=/"
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]

现在只需从同一文件夹中 运行 Docker 命令来创建图像。当然,这需要在您的开发箱上安装 Docker 客户端。

$ docker build -t myapp:0.1.8 --force-rm=true --no-cache=true .

如果一切顺利,您应该会看到使用 docker ps 命令列出的图像

部署到私有 ECR 存储库

将新映像部署到 ECR 存储库很容易,而且 ECR 开箱即可与 EKS 配合使用。登录 AWS 控制台并导航至 the ECR section。我发现很困惑,显然你需要为每个图像创建一个存储库,但是当你单击 "Create repository" 按钮时,将你的图像名称(例如 myapp)输入文本字段。现在你需要为你的图像复制丑陋的 URL 并返回到命令提示符

标记并推送您的图像。我以假 URL 为例:901237695701.dkr.ecr.us-west-2.amazonaws.com 你需要从上一步复制你自己的

$ docker tag myapp:0.1.8 901237695701.dkr.ecr.us-west-2.amazonaws.com/myapp:latest
$ docker push 901237695701.dkr.ecr.us-west-2.amazonaws.com/myapp:latest

此时图像应该显示在您创建的 ECR 存储库中

将您的应用程序部署到 EKS 集群

现在您需要为应用的 Docker 映像创建 Kubernetes 部署。使用以下内容创建一个 myapp-deployment.yaml 文件

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  selector:
    matchLabels:
      app: myapp
  replicas: 2
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: 901237695701.dkr.ecr.us-west-2.amazonaws.com/myapp:latest
        name: myapp
        ports:
        - containerPort: 8080
          name: server
        env:
        # optional
        - name: RDS_HOSTNAME
          value: "10.100.98.196"
        - name: RDS_PORT
          value: "3306"
        - name: RDS_DB_NAME
          value: "mydb"
      restartPolicy: Always
status: {}

请注意我如何为 image 参数使用完整的 URL。我还使用了 mysql 集群的私有 CLUSTER-IP,您可以使用 kubectl get svc my-cluster-mysql 命令获得它。这将因您的应用程序而异,包括任何环境名称,但您必须以某种方式向您的应用程序提供此信息。然后在您的应用程序中,您可以在 application.properties 文件中设置如下内容:

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://${RDS_HOSTNAME}:${RDS_PORT}/${RDS_DB_NAME}?autoReconnect=true&zeroDateTimeBehavior=convertToNull
spring.datasource.username=${RDS_USERNAME}
spring.datasource.password=${RDS_PASSWORD}

保存 myapp-deployment.yaml 后,您需要 运行 此命令

kubectl apply -f myapp-deployment.yaml

这会将您的应用程序部署到 EKS 集群中。这将在集群中创建 2 pods,您可以使用 kubectl get pods 命令

查看

与其尝试直接访问其中一个 pods,我们还可以创建一个服务来前端应用程序 pods。使用以下内容创建 myapp-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  ports:
  - port: 443
    targetPort: 8080
    protocol: TCP
    name: http
  selector:
    app: myapp
  type: LoadBalancer

这就是奇迹发生的地方!只需将端口设置为 443 并输入 LoadBalancer,系统就会创建一个 Classic Load Balancer 来放置您的应用程序。

顺便说一句,如果您不需要通过 HTTPS 运行 您的应用程序,您可以将端口设置为 80,这样就大功告成了!

在 运行 kubectl apply -f myapp-service.yaml 集群中的服务将被创建,如果您转到 AWS 控制台 EC2 部分的负载均衡器部分,您将看到一个新的均衡器是为你创造。您还可以使用 运行 kubectl get svc myapp-service 命令,它会为您提供 EXTERNAL-IP 值,类似于 bl3a3e072346011e98cac0a1468f945b-8158249.us-west-2.elb.amazonaws.com。复制它,因为我们接下来需要使用它。

值得一提的是,如果您使用的是端口 80,那么只需将 URL 粘贴到浏览器中即可显示您的应用程序

通过 HTTPS 访问您的应用程序

以下部分假定您拥有 AWS 颁发的 SSL 证书。如果您不这样做,请转到 AWS 控制台 "Certificate Manager" 并为您的域创建一个通配符证书

在您的负载平衡器可以工作之前,您需要访问 AWS console -> EC2 -> Load Balancers -> My new balancer -> Listeners 并单击 SSL Certificate 列中的 "Change" link。然后在弹出的selectAWS颁发的SSL证书中保存

转到 AWS 控制台中的 Route-53 部分和 select 您域的托管区域,例如 myapp.com.。然后单击 "Create Record Set" 并创建一个 CNAME - Canonical name 记录,其中 Name 设置为您想要的任何别名,比如 cluster.myapp.comValue 设置为上面的 EXTERNAL-IP。在你 "Save Record Set" 进入你的浏览器并输入 https://cluster.myapp.com 之后。您应该会看到您的应用 运行ning