一、准备工作
0. 基本概念
Node
):一个节点是一个运行 Kubernetes 中的主机。Pod
):一个 Pod 对应于由若干容器组成的一个容器组,同个组内的容器共享一个存储卷(volume)。pos-states
):包含所有容器状态集合,包括容器组状态类型,容器组生命周期,事件,重启策略,以及 replication controllers。services
):一个 Kubernetes 服务是容器组逻辑的高级抽象,同时也对外提供访问容器组的策略。volumes
):一个卷就是一个目录,容器对其有访问权限。labels
):标签是用来连接一组对象的,比如容器组。标签可以被用来组织和选择子对象。accessing_the_api
):端口,IP 地址和代理的防火墙规则。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