K8s入门手记

一、准备工作

0. 基本概念

  • 节点(Node):一个节点是一个运行 Kubernetes 中的主机。
  • 容器组(Pod):一个 Pod 对应于由若干容器组成的一个容器组,同个组内的容器共享一个存储卷(volume)。
  • 容器组生命周期(pos-states):包含所有容器状态集合,包括容器组状态类型,容器组生命周期,事件,重启策略,以及 replication controllers。
  • Replication Controllers:主要负责指定数量的 pod 在同一时间一起运行。
  • 服务(services):一个 Kubernetes 服务是容器组逻辑的高级抽象,同时也对外提供访问容器组的策略。
  • 卷(volumes):一个卷就是一个目录,容器对其有访问权限。
  • 标签(labels):标签是用来连接一组对象的,比如容器组。标签可以被用来组织和选择子对象。
  • 接口权限(accessing_the_api):端口,IP 地址和代理的防火墙规则。
  • web 界面(ux):用户可以通过 web 界面操作 Kubernetes。
  • 命令行操作(cli):kubecfg命令。

1. 制作一个镜像

用go写一个简单的httpsvr,代码如下:

package main

import (
    "fmt"
    "log"
    "net/http"
)

func homePage(writer http.ResponseWriter, request *http.Request) {
    err := request.ParseForm()

    fmt.Fprint(writer, "")
    if err != nil {
        fmt.Fprintf(writer, "%s", err)
    }
    content, found := request.Form["name"]
    if found {
        fmt.Fprintf(writer, "%s", content)
    }
    fmt.Fprint(writer, "")
}

func main() {
    http.HandleFunc("/", homePage)
    err := http.ListenAndServe(":9001", nil)
    if err != nil {
        log.Fatal("failed to start server", err)
    }
}

撰写Dockerfile,这里的scratch表示为基础镜像的话,意味着你不以任何镜像为基础,接下来所写的指令将作为镜像第一层开始存在。

# Dockerfile References: https://docs.docker.com/engine/reference/builder/

# Start from golang v1.11 base image
FROM golang:1.11

# Add Maintainer Info
LABEL maintainer="[email protected]"

# Set the Current Working Directory inside the container
WORKDIR $GOPATH/src/github.com/callicoder/go-docker

# Copy everything from the current directory to the PWD(Present Working Directory) inside the container
COPY . .

# Download all the dependencies
# https://stackoverflow.com/questions/28031603/what-do-three-dots-mean-in-go-command-line-invocations
RUN go get -d -v ./...

# Install the package
RUN go install -v ./...

# This container exposes port 8080 to the outside world
EXPOSE 9001

# Run the executable
ENTRYPOINT ["./http_demo"]

 

#FROM scratch
FROM golang:1.11

# Copy everything from the current directory to the PWD(Present Working Directory) inside the container
COPY . .

#start
EXPOSE 9001

# Run the executable
ENTRYPOINT ["./http_demo"]
$ docker build -t http_demo:v1 .
Sending build context to Docker daemon  6.572MB
Step 1/3 : FROM scratch
 ---> 
Step 2/3 : EXPOSE 9001
 ---> Running in e79fcce5b314
Removing intermediate container e79fcce5b314
 ---> e4318ba62c4f
Step 3/3 : CMD    ["./http_demo"]
 ---> Running in 0b01a5a221f0
Removing intermediate container 0b01a5a221f0
 ---> 73ba3f4115ec
Successfully built 73ba3f4115ec
Successfully tagged http_demo:v1

build成功后,可以查看已创建。

docker image ls
REPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZE
http_demo                                  v1                  73ba3f4115ec        About an hour ago   0B

2. 创建一个pod

使用kubectl run创建一个deployment。

$ kubectl run http-demo --image=http_demo:v20 --port=9001

deployment.apps "http-demo" created

查看deployment运行状态

$ kubectl get deployments

NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE

http-demo   1         1         1            0           43s

查看pod运行状态

$ kubectl get pods

NAME                        READY     STATUS              RESTARTS   AGE

http-demo-6c95d79fd-5wckb   0/1       ImageInspectError   0          2m

3. 删除pod

$ kubectl delete pod http-demo-6c95d79fd-5wckb

pod "http-demo-6c95d79fd-5wckb" deleted

$ kubectl delete deployment http-demo

deployment.extensions "http-demo" deleted

4. 开启对外开放

上面的webserver监听9001端口,但这时netstant -ant | grep 9001查不到端口监听,原因是默认情况下,pod 只可以在 Kubernetes 群集内部访问,为了使容器可以从 Kubernetes 虚拟网络外访问,你必须用 Kubernetes service 让 pod 对外开放。

$ kubectl expose deployment http-demo --type="LoadBalancer"

service "http-demo" exposed

这时可以进行测试,同时也可以直接用curl访问

$ netstat -ant | grep 9001

tcp6       0      0  ::1.9001               *.*                    LISTEN     

tcp4       0      0  *.9001                 *.*                    LISTEN

也可以查询service.

$ kubectl get services http-demo

NAME        TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE

http-demo   LoadBalancer   10.101.6.223   localhost     9001:30945/TCP   2m

 

二、扩容与部署

1. Kubernetes 的强大功能之一就是他可以很容易的扩容你的应用程序。假设你突然需要增加你的应用;你只需要告诉deployment一个新的 pod 副本总数即可:

$ kubectl scale deployment http-demo --replicas=2

deployment.extensions "http-demo" scaled

现在,我们拥有2个应用副本了,每个在集群上独立运行,并能够负载均衡。

$ kubectl get deployment

NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE

http-demo   2         2         2            2           8m

$ kubectl get pods

NAME                         READY     STATUS    RESTARTS   AGE

http-demo-55cb77556b-fgkl4   1/1       Running   0          9m

http-demo-55cb77556b-x4nn2   1/1       Running   0          1m

 

2. 滚动更新

下面我们来测试下滚动更新功能,修改下http_demo.go,增加一个输出,构建一个新版本镜像

$ docker build -t http_demo:v22 .

设置并更新到新版本

$ kubectl set image deployment/http-demo http-demo=http_demo:v22

deployment.apps "http-demo" image updated

这次可以查看

$ kubectl get deployments

NAME        DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE

http-demo   2         2         2            2           2h

$ kubectl get pods

NAME                         READY     STATUS    RESTARTS   AGE

http-demo-54fcd8d969-lrjnt   1/1       Running   0          1m

http-demo-54fcd8d969-r75f6   1/1       Running   0          1m

可以用curl进行测试输出

$ curl 127.0.0.1:9001

This is a new version.

 

三、进阶

1. 使用YAML文件创建,以上面的http_demo:v22镜像为例,创建一个新的deployment

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: http-demo2
spec:
  replicas: 3
  template:
    metadata:
      labels:
        run: http-demo2
    spec:
      containers:
      - name: http-demo
        image: http_demo:v22
        ports:
        - containerPort: 9001

kubectl create -f ./appgo.yaml

2. 可以通过consle或者webui查看,http://localhost:8001/api/v1/namespaces/kube-system/services/https:kubernetes-dashboard:/proxy/#!/overview?namespace=default

使用webui前需要启动kubectl proxy

3. 下面测试下多个容器打到一个pod中

创建两个进程,分别监听9002和9003端口

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: web-demo
spec:
  replicas: 3
  template:
    metadata:
      labels:
        run: web-demo
    spec:
      containers:
      - name: web-9002
        image: web_9002:v1
        ports:
        - containerPort: 9002
      - name: web-9003
        image: web-9003:v1
        ports:
        - containerPort: 9003

创建并暴露端口。

kubectl create -f ./appgo.yaml 

kubectl expose deployment web-demo --type="LoadBalancer"

可以查看pods和services

kubectl get pods

NAME                        READY     STATUS             RESTARTS   AGE

http-demo-c7fff58fb-7ccrl   1/1       Running            0          1d

http-demo-c7fff58fb-kpvp6   1/1       Running            0          1d

web-demo-7b5cdcfd4c-5kcn4   0/2       ImagePullBackOff   0          1m

web-demo-7b5cdcfd4c-ftqft   0/2       ImagePullBackOff   0          1m

web-demo-7b5cdcfd4c-rrg4v   0/2       ImagePullBackOff   0          1m

wangyachangdeMacBook-Pro:appgo wangyachang$ kubectl get services

NAME         TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                         AGE

http-demo    LoadBalancer   10.101.6.223     localhost     9001:30945/TCP                  1d

http-demo2   LoadBalancer   10.106.186.205        9001:31759/TCP                  18h

kubernetes   ClusterIP      10.96.0.1                443/TCP                         13d

web-demo     LoadBalancer   10.99.58.137     localhost     9002:30649/TCP,9003:31801/TCP   3m

在写yaml文件的时候发现,image必须指定版本号,不能用latest.

4. 测试进程监控和重启

在web-9002和web-9003中,预留了一个控制命令可以使进程退出,这里测试下退出后,查看进程状态,可以看到在不同的pods中有出现重启的情况.

$ kubectl get pods
NAME                        READY     STATUS    RESTARTS   AGE
http-demo-c7fff58fb-7ccrl   1/1       Running   0          1d
http-demo-c7fff58fb-kpvp6   1/1       Running   0          1d
web-demo-cc75bcdd5-5j65n    2/2       Running   1          6m
web-demo-cc75bcdd5-q4wwl    2/2       Running   2          6m
web-demo-cc75bcdd5-ztc26    2/2       Running   0          6m

5. 测试伸缩性

$ kubectl autoscale deployment web-demo --cpu-percent=50 --min=2 --max=5

deployment.apps "web-demo" autoscaled

测试前,先调整部署web-demo为1个,设置后可以查看当前状态和数量,如下所示,正在启动中

$ kubectl get pods
NAME                        READY     STATUS              RESTARTS   AGE
http-demo-c7fff58fb-7ccrl   1/1       Running             0          1d
http-demo-c7fff58fb-kpvp6   1/1       Running             0          1d
web-demo-cc75bcdd5-df5nq    2/2       Running             0          5h
web-demo-cc75bcdd5-v8n5q    0/2       ContainerCreating   0          1s

四、Configmap

服务在运行时,会存在可执行文件和配置文件,而在不同环境中,配置文件一般会存在差异,比如一些外部接口的路由信息、日志级别等。所以在进程管理上需要控制镜像和配置的分离。k8s提供了configmap的机制,作为k8s的资源对象,内容保存在etcd中。

ConfigMap的用处有以下几种: 
1. 生成为容器内的环境变量 
2. 设置容器启动的命令参数 
3. volume形式挂载成容器内的文件或目录

创建ConfigMap的方式有4种:

通过直接在命令行中指定configmap参数创建,即--from-literal
通过指定文件创建,即将一个配置文件创建为一个ConfigMap--from-file=<文件>
通过指定目录创建,即将一个目录下的所有配置文件创建为一个ConfigMap,--from-file=<目录>
事先写好标准的configmap的yaml文件,然后kubectl create -f 创建
下面我们分别用前两种方式给web_demo添加configmap.

1. --from-literal

wangyachangdeMacBook-Pro:mail wangyachang$ kubectl get cm web-demo
NAME       DATA      AGE
web-demo   2         1m
wangyachangdeMacBook-Pro:mail wangyachang$ kubectl get configmap web-demo -o yaml
apiVersion: v1
data:
  bind.host: 127.0.0.1
  bind.port: "9001"
kind: ConfigMap
metadata:
  creationTimestamp: 2019-04-08T00:59:23Z
  name: web-demo
  namespace: default
  resourceVersion: "1210774"
  selfLink: /api/v1/namespaces/default/configmaps/web-demo
  uid: 8c54c91b-5999-11e9-8f24-025000000001

2.--from-file

wangyachangdeMacBook-Pro:appgo wangyachang$ cat web-demo.conf
[web-9002]
host:localhost
port:9002

[web-9003]
host:127.0.0.1
port:9003

wangyachangdeMacBook-Pro:appgo wangyachang$ kubectl create configmap web-demo --from-file=web-demo.conf 
configmap "web-demo" created

wangyachangdeMacBook-Pro:appgo wangyachang$ kubectl get configmap web-demo -o yaml
apiVersion: v1
data:
  web-demo.conf: |
    [web-9002]
    host:localhost
    port:9002

    [web-9003]
    host:127.0.0.1
    port:9003
kind: ConfigMap
metadata:
  creationTimestamp: 2019-04-08T01:07:07Z
  name: web-demo
  namespace: default
  resourceVersion: "1211289"
  selfLink: /api/v1/namespaces/default/configmaps/web-demo
  uid: a132529b-599a-11e9-8f24-025000000001

下面,我们来看下如何使用。kubectl edit -f appgo.yaml 进行编辑模式 

      containers:
      - image: web_9002:v1
        imagePullPolicy: IfNotPresent
        name: web-9002
        ports:
        - containerPort: 9002
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
      - image: web_9003:v1
        imagePullPolicy: IfNotPresent
        name: web-9003
        ports:
        - containerPort: 9003
          protocol: TCP
        resources: {}
        terminationMessagePath: /dev/termination-log
        terminationMessagePolicy: File
        volumeMounts:
        - mountPath: /tmp
          name: config-volume
      dnsPolicy: ClusterFirst
      restartPolicy: Always
      schedulerName: default-scheduler
      securityContext: {}
      terminationGracePeriodSeconds: 30
      volumes:
      - configMap:
          defaultMode: 420
          name: web-demo-cfg1
        name: config-volume

更新完yaml文件后,可以进入容器查看。

wangyachangdeMacBook-Pro:appgo wangyachang$ docker exec -it 5581 /bin/bash
root@web-demo-66f8d46cc9-5vmwn:/go# ls /tmp/
web-demo.conf
root@web-demo-66f8d46cc9-5vmwn:/go# cat /tmp/web-demo.conf 
[web-9002]
host:localhost
port:9002

[web-9003]
host:127.0.0.1
port:9003

五、Helm

安装Helm参考下面的链接,这里安装的版本是2.9.1 ,下面我们来看如何用Helm来管理yaml文件。

Client: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}

Server: &version.Version{SemVer:"v2.9.1", GitCommit:"20adb27c7c5868466912eebdf6664e7390ebe710", GitTreeState:"clean"}

依以web_9004为例,我们创建一个websvr的chart包,然后进行部署。

5. 1 创建chart包,helm create websvr,如下所示,其中values.yaml是定义,templates下是各个yaml文件的模版。

ls -al
total 24
drwxr-xr-x  7 wangyachang  staff   224  4 23 14:33 .
drwxr-xr-x  3 wangyachang  staff    96  4 22 17:25 ..
-rw-r--r--  1 wangyachang  staff   342  4 22 17:25 .helmignore
-rw-r--r--  1 wangyachang  staff   102  4 22 17:25 Chart.yaml
drwxr-xr-x  2 wangyachang  staff    64  4 22 17:25 charts
drwxr-xr-x  8 wangyachang  staff   256  4 23 14:28 templates
-rw-r--r--  1 wangyachang  staff  1081  4 23 14:29 values.yaml

修改values.yaml文件中的image和service部分,这里指定了镜像的name:tag,以及开启lb和port,从而可以对方提供服务.

image:
  repository: web_9004
  tag: v4
  pullPolicy: IfNotPresent

nameOverride: ""
fullnameOverride: ""

service:
  type: LoadBalancer
  port: 9004

values.yaml用于生成templates下具体的各个yaml文件,以service.yaml模板为例,模板中的type和port分别取自values.yaml中的定义,就是上面的"LoadBalance"和9004.

spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http

然后,可以执行helm install --dry-run --debug websvr来校验生成的yaml是否正确,检查ok后,可以执行helm install .安装。

安装后可以查看。

$ kubectl get all | grep websvr
pod/ranting-rabbit-websvr-7c9f98bb6-ng4db   1/1       Running   0          15m

service/ranting-rabbit-websvr   LoadBalancer   10.98.118.10     localhost     9004:30457/TCP                  15m

deployment.apps/ranting-rabbit-websvr   1         1         1            1           15m

replicaset.apps/ranting-rabbit-websvr-7c9f98bb6   1         1         1         15m

可以通过helm list、helm delete进行查看到删除。

参考:

http://docs.kubernetes.org.cn 中文文档

https://www.cnblogs.com/miaoying/p/10301125.html - MAC搭建dashboard

http://kubernetes.kansea.com/docs/hellonode/

https://yeasy.gitbooks.io/docker_practice/kubernetes/design.html

https://www.jb51.net/article/129003.htm

https://blog.csdn.net/liukuan73/article/details/79492374 

https://www.cnblogs.com/dazhoushuoceshi/p/7066041.html Dockerfile 详解

https://blog.csdn.net/bbwangj/article/details/81087911 Helm

你可能感兴趣的:(Go)