使用HELM发布到Kubernetes


当发布应用到Kubernetes时,Helm是必备工具。 让我们来演示一下原因。

演示的目标

  • 如何将Spring Boot应用程序打包为Kubernetes Helm chart
  • 如何作为Kubernetes Helm chart安装Spring Boot应用程序
  • 如何通过Kubernetes Helm升级安装的Spring Boot应用程序
  • 如何将通过Kubernetes Helm将安装的Spring Boot应用程序回滚到以前的版本

先决条件
  • Kubernetes minikube安装
  • Spring Boot应用程序

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

    /**
    * Created by tomask79 on 20.06.18.
    */

    @RestController
    public class ControllerMVC {

        @RequestMapping(
"/sayhello")
        public String mvcTest() {
            return
"I'm saying hello to Kubernetes!";
        }
    }

用于构建Docker镜像的Dockerfile:

FROM openjdk:8-jre
MAINTAINER Tomas Kloucek <tomas.kloucek@embedit.cz>

ENTRYPOINT ["/usr/bin/java", "-jar", "/usr/share/myservice/myservice.jar"]

# Add the service itself
ARG JAR_FILE
ADD target/${JAR_FILE} /usr/share/myservice/myservice.jar

我喜欢直接从maven构建Docker镜像,构建是由 Dockerfile maven插件引起的。因此在pom.xml中添加了:

<plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.7</version>
            <executions>
                <execution>
                    <id>default</id>
                    <goals>
                        <goal>build</goal>
                    </goals>
                </execution>
            </executions>
            <configuration>
                <repository>test-mvc</repository>
                <tag>${project.version}</tag>
                <buildArgs>
                    <JAR_FILE>${project.build.finalName}.jar</JAR_FILE>
                </buildArgs>
            </configuration>
        </plugin>


如何安装Kubernetes Helm
检查Helm安装指南并根据您的操作系统执行相应步骤。 在我的情况下,我有MacOS所以我做了以下:

  • brew安装kubernetes-helm
  • helm init

“Helm init”将名为Tiller(Helm服务器)的必要Helm组件安装 到由kubectl config current-context 返回的kubernetes集群中。所以你需要在此之前启动你的minikube。

要验证Tiller是否准备就绪,请运行:

$ kubectl -n kube-system get pods
NAME                                    READY     STATUS    RESTARTS   AGE
etcd-minikube                           1/1       Running   0          9m
kube-addon-manager-minikube             1/1       Running   0          9m
kube-apiserver-minikube                 1/1       Running   0          9m
kube-controller-manager-minikube        1/1       Running   0          9m
kube-dns-86f4d74b45-nvvw4               3/3       Running   0          10m
kube-proxy-gd2m6                        1/1       Running   0          10m
kube-scheduler-minikube                 1/1       Running   0          9m
kubernetes-dashboard-5498ccf677-sbvvd   1/1       Running   0          10m
storage-provisioner                     1/1       Running   0          10m
tiller-deploy-6fd8d857bc-b4hpg          1/1       Running   0          15s


好的,现在你应该为Helming做好准备了!

为Helming构建Docker镜像
首先切换你的docker,与在minikube里面运行的docker 守护进程交互:

$ eval $(minikube docker-env)​​​​​​​

现在最终构建应用程序和docker镜像:

$ mvn clean install

然后改变案例中/ sayhello端点输出内容,更改为输出其他内容并使用 pom.xml中的不同$ {project.version}再次运行mvn clean install。这将导致创建另一个Docker镜像。最后你应该发现:

$ docker images
REPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZE
test-mvc                                   0.0.1-SNAPSHOT      8bb54cac5fdd        8 seconds ago       459MB
test-mvc                                   0.0.2-SNAPSHOT      69498681609d        2 minutes ago       459MB
openjdk                                    8-jre               60648c86cfe8        8 days ago          443MB
gcr.io/kubernetes-helm/tiller              v2.11.0             ac5f7ee9ae7e        4 weeks ago         71.8MB

创建和打包HELM chart
要创建一个空的Helm chart,只需运行:

$ helm create testmvc-chart
Creating testmvc-chart

之后,您将获得chart的模板文件。 
如果您打开deployment.yaml或service.yaml,您将看到三种类型的值:

{{ template  chart.fullname. }} # values from Chart.yaml 
{{ .Release.Name }} # built in Release object
{{ .Values.replicaCount }} # value from values.yaml

这意味着:

  • 您可以参数化您的Kubernetes清单
  • HELM将立即安装它们!
  • HELM能够立刻丢弃它们!
  • HELM能够立即升级和回滚它们!

这些是你应该接受HELM的主要原因。 
首先编辑你的values.yaml和internalPort,因为我们将 使用NodePort服务。

replicaCount: 1
image:
    repository: test-mvc
    tag: 0.0.1-SNAPSHOT
    pullPolicy: IfNotPresent
service:
    name: testmvc
    type: NodePort
    externalPort: 8081
    internalPort: 8081
ingress:
    enabled: false
    # Used to create an Ingress record.
    hosts:
        - chart-example.local
    annotations:
        # kubernetes.io/ingress.class: nginx
        # kubernetes.io/tls-acme: "true"
    tls:
        # Secrets must be manually created in the namespace.
        # - secretName: chart-example-tls
        #   hosts:
        #     - chart-example.local
resources: {}

后使用deployment.yaml模板,镜像详细信息取自values.yaml:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
    name: {{ .Chart.Name }}
spec:
    replicas: {{ .Values.replicaCount }}
template: 
    metadata:
        labels:
        app: {{ .Chart.Name }}
    spec:
    containers:
    - name: {{ .Chart.Name }}
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        ports:
        - containerPort: {{ .Values.service.internalPort }}

service.yaml 将包含NodePort设置,请在values.yaml中检查service.type:

apiVersion: v1
kind: Service
metadata:
    name: {{ .Chart.Name }}
labels:
    name: {{ .Chart.Name }}
spec:
    type: {{ .Values.service.type }}
ports:
  - port: {{ .Values.service.externalPort}}
    targetPort: {{ .Values.service.internalPort}}
selector:
    app: {{ .Chart.Name }}

模板准备好了,所以让我们 用我的演示应用程序的第一个版本为第一个docker镜像创建和打包chart

$ helm package ./testmvc-chart --debug
Successfully packaged chart and saved it to: /Users/tomask79/workspace/testmvc-chart-0.1.0.tgz
[debug] Successfully saved /Users/tomask79/workspace/testmvc-chart-0.1.0.tgz to /Users/tomask79/.helm/repository/local

要准备升级chart,让我们修改Chart.yaml并升级版本:

apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: testmvc-chart
version: 0.2.0

并升级values.yaml中的镜像版本:

image:
    repository: test-mvc
    tag: 0.0.2-SNAPSHOT
    pullPolicy: IfNotPresent

现在让我们再次构建一个chart,但这次是我们的应用程序的新版本:

$ helm package ./testmvc-chart --debug
Successfully packaged chart and saved it to: /Users/tomask79/workspace/testmvc-chart-0.2.0.tgz
[debug] Successfully saved /Users/tomask79/workspace/testmvc-chart-0.2.0.tgz to /Users/tomask79/.helm/repository/local

我将这两个chart附加到这个仓库,但我想告诉你我是如何构建它们的。

安装HELM Chart
好的,应用程序准备好在两个指向不同Dockers镜像的HELM图表中。

$ ls -l | grep ".gz"
-rw-r--r--  1 tomask79  staff  2268 Oct 25 22:06 testmvc-chart-0.1.0.tgz
-rw-r--r--  1 tomask79  staff  2268 Oct 25 22:11 testmvc-chart-0.2.0.tgz

安装第一个:

$ helm install -n testmv-chart testmvc-chart-0.1.0.tgz 
NAME:   testmv-chart
    LAST DEPLOYED: Thu Oct 25 22:19:53 2018
    NAMESPACE: default
    STATUS: DEPLOYED

RESOURCES:
==> v1/Service
NAME           AGE
testmvc-chart  0s

==> v1beta1/Deployment
testmvc-chart  0s

==> v1/Pod(related)

NAME                            READY  STATUS             RESTARTS  AGE
testmvc-chart-595dcdd84b-2mm4t  0/1    ContainerCreating  0         0s


NOTES:
1. Get the application URL by running these commands:
 export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services testmv-chart-testmvc-chart)
 export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath=
"{.items[0].status.addresses[0].address}")
 echo http:
//$NODE_IP:$NODE_PORT

确认验证app POD是否在运行:

$ kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE
testmvc-chart-595dcdd84b-2mm4t   1/1       Running   0          2m

HELM 也有你的安装列表:

$ helm list
NAME            REVISION    UPDATED                     STATUS      CHART               APP VERSION NAMESPACE
testmv-chart    1           Thu Oct 25 22:19:53 2018    DEPLOYED    testmvc-chart-0.1.0 1.0         default

测试一下:

$ kubectl get services
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes      ClusterIP   10.96.0.1       <none>        443/TCP          1d
testmvc-chart   NodePort    10.100.60.180   <none>        8081:31804/TCP   4m
Macbooks-MacBook-Pro:workspace tomask79$ 
Macbooks-MacBook-Pro:workspace tomask79$ minikube service testmvc-chart --url
http://192.168.99.100:31804
Macbooks-MacBook-Pro:workspace tomask79$ curl http:
//192.168.99.100:31804/sayhello
I'm saying hello to Kubernetes!

再次注意,我们安装了整个K8s包,只需安装一个Hlem

将HELM chart升级到新版本
在testmvc-chart-0.2.0.tgz中也有我们的Spring Boot应用程序,被打包的版本2 中,所以让我们升级现有的HELM chart:

$ helm upgrade testmv-chart testmvc-chart-0.2.0.tgz
Release "testmv-chart" has been upgraded. Happy Helming!
LAST DEPLOYED: Thu Oct 25 22:40:36 2018
NAMESPACE: default
STATUS: DEPLOYED

RESOURCES:
==> v1/Pod(related)
NAME                            READY  STATUS       RESTARTS  AGE
testmvc-chart-595dcdd84b-8mbpm  1/1    Terminating  0         16s
testmvc-chart-74d945c54f-7l8rm  0/1    Pending      0         0s

==> v1/Service

NAME           AGE
testmvc-chart  20m

==> v1beta1/Deployment
testmvc-chart  20m


NOTES:
1. Get the application URL by running these commands:
    export NODE_PORT=$(kubectl get --namespace default -o jsonpath=
"{.spec.ports[0].nodePort}" services testmv-chart-testmvc-chart)
    export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath=
"{.items[0].status.addresses[0].address}")
    echo http:
//$NODE_IP:$NODE_PORT

好的,让我们检查升级的PODS是否正在运行并测试应用程序:

$ kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE
testmvc-chart-74d945c54f-7l8rm   1/1       Running   0          2m
Macbooks-MacBook-Pro:workspace tomask79$ minikube service testmvc-chart --url
http://192.168.99.100:31804
Macbooks-MacBook-Pro:workspace tomask79$ curl http:
//192.168.99.100:31804/sayhello
I'm saying hello to Kubernetes in the V2!

将chart回滚到以前的版本
使用HELM在K8s中回滚到以前的版本非常简单:

$ helm rollback testmv-chart 0
Rollback was a success! Happy Helming!
Macbooks-MacBook-Pro:workspace tomask79$ helm list
NAME            REVISION    UPDATED                     STATUS      CHART               APP VERSION NAMESPACE
testmv-chart    5           Thu Oct 25 22:55:28 2018    DEPLOYED    testmvc-chart-0.1.0 1.0         default

让我们检查一下我们是否真的回到第一版:

$ minikube service testmvc-chart --url
http://192.168.99.100:31804
$ curl http:
//192.168.99.100:31804/sayhello
I'm saying hello to Kubernetes!

​​​​​​​