Manjaro安装vscode和edge

这个方法是从archlinux build源手工安装软件。首先需要安装基础的软件包,再下载源编译和安装。

阅读更多

使用pandoc生成PPT常用命令

使用markdown + marp或者markdown + revealjs可以写PPT。使文档写作过程只专注于写作本身而不是各种格式。其实第一次还是要将常用的格式做好调试(主要是写一些常用的css文件自定义样式),后续则可以在markdown->html/PDF/docx/pptx/ebook间随意转换了。

以下主要记录几个常用命令,完整的pandoc手册可以参考:https://pandoc.org/MANUAL.html

  • markdown 2 pptx
    pandoc mark.md -o mark.pptx --reference-doc=template.potx

  • mardown 2 revealjs
    pandoc -t revealjs mark.md -o mark.html --self-contained -V revealjs-url=./reveal.js/ --css=custom.css

-t 参数还可以设置成s5, slidy, slideous, dzslides;
-V revealjs-url 可以制定本地目录reveal.js, 将https://github.com/hakimel/reveal.js下载本地即可;
-css 可以制定css附件,通过定制css文件可以调整显示样式。

  • 对于revealjs可以在文件中设置width和height调整显示大小

    • markdown文件示例文件如下:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    ---
    title: 使用pandoc生成PPT常用命令
    theme: white
    width: 1920
    height: 1280
    author:
    - author
    date: 2021-09-14
    ---

    # markdown2pptx

    `pandoc mark.md -o mark.pptx --reference-doc=template.potx`

    ---

    # markdown2revealjs

    `pandoc -t revealjs mark.md -o mark.html --self-contained -V revealjs-url=./reveal.js/ --css=custom.css`

    • css文件示例
    1
    2
    3
    .reveal h1{
    color:olivedrab
    }

配置Manjaro Linux上ibus-rime输入法

在Manjaro系统中不能直接通过ibus-setup设置ibus-rime显示模式为水平模式(可能是Manjaro的bug)只能设置字体和文字大小。可以通过直接修改ibus-rime配置文件配置想要的显示方式。

ibus-rime的配置文件默认在~/.config/ibus/rime/build/目录下,直接将horizontal配置项修改成true即可。

其他的ibus配置可以参考https://wiki.archlinux.org/title/IBus

minikube addons enable ingress

由于大家都知道到原因,国内无法直接访问gcr.io和quay.io很多Kubernetes相关镜像无法从国内下载,网上很多大神也给出了薅aliyun羊毛的方案,我自己也试了几次也总是不能成功,使用aliyun提供minikube的版本也总是无法启动ingress。

通过查看启动ingress失败的POD信息发现是无法下载使用到镜像,于是按照网络指导按照如下步骤提前下载镜像到minikube节点,再启动ingress即可成功,具体操作如下:

  • 查询minikube版本对应的ingress镜像版本使用kubectl get po -A查询ingress对应POD

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    kubectl get po -A
    NAMESPACE NAME READY STATUS RESTARTS AGE
    kube-system coredns-546565776c-xgggd 1/1 Running 0 27m
    kube-system etcd-minikube 1/1 Running 0 27m
    kube-system ingress-nginx-admission-create-d9dtl 0/1 Completed 0 28s
    kube-system ingress-nginx-admission-patch-x67q7 0/1 Completed 1 28s
    kube-system ingress-nginx-controller-7bb4c67d67-hp5c7 0/1 ContainerCreating 0 28s
    kube-system kube-apiserver-minikube 1/1 Running 0 27m
    kube-system kube-controller-manager-minikube 1/1 Running 0 27m
    kube-system kube-proxy-7wbct 1/1 Running 0 27m
    kube-system kube-scheduler-minikube 1/1 Running 0 27m
    kube-system storage-provisioner 1/1 Running 0 27m

    其中名字中包含ingress就是启动ingress新建到POD。

    再使用kubectl describe po ingress-nginx-xxx --namespace kube-system查询具体的失败信息,即可查询到失败原因为:获取镜像失败/超时。由于minikube 1.12.0版本以上的ingress镜像目前在阿里云上也无法下载,我们将minikube的版本切换到1.12.0版本,此时查询到的ingress插件依赖镜像信息如下:

    1
    2
    quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.32.0
    jettech/kube-webhook-certgen:v1.2.0
  • 手动安装ingress镜像使用minikube ssh登录到minikube的节点上,再动过docker命令手工pull镜像。

    1
    2
    3
    docker pull registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.32.0
    docker tag registry.cn-hangzhou.aliyuncs.com/google_containers/nginx-ingress-controller:0.32.0 quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.32.0
    docker pull jettech/kube-webhook-certgen:v1.2.0

    quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.32.0 镜像可以由aliyun的镜像替代,再重新Tag成原有镜像。

  • 再次启用ingress
    上述操作均成功以后可以再次启动ingress插件即可秒成功 :)

Kubernetes部署和升级应用

之前文章中我们都是用POD部署应用,特别是用POD部署应用时如果要更新应用程序,必须先更新镜像(Image)/配置(ConfigMap),删除POD再重新部署应用程序才能整整的更新。Kubernetes提供了更高级的应用部署和升级方法。

使用ReplicationController部署应用

如果用ReplicationController(RC)部署的应用可以通过RC update来更新应用。具体的kubia-rc.yaml文件如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: v1
kind: ReplicationController
metadata:
name: kubia
spec:
replicas: 3
selector:
app: kubia
template:
metadata:
name: kubia
labels:
app: kubia
spec:
containers:
- name: kubia
image: 172.17.0.1:5000/kubia:v1
ports:
- containerPort: 3000

使用kubectl create -f kubia-rc.yaml创建RC,部署成功以后即可看到根据RC的配置会产生3个副本kubectl get rc,po

1
2
3
4
5
6
7
8
9
kubectl get po,rc
NAME READY STATUS RESTARTS AGE
pod/kubia-bqszw 1/1 Running 0 62s
pod/kubia-c4cb9 1/1 Running 0 62s
pod/kubia-wxj55 1/1 Running 0 62s

NAME DESIRED CURRENT READY AGE
replicationcontroller/kubia 3 3 3 62s

当前POD到到镜像版本为v1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kubectl describe po
Name: kubia-bqszw
Namespace: default
Priority: 0
Node: minikube/172.17.0.3
Start Time: Wed, 14 Oct 2020 20:29:56 +0800
Labels: app=kubia
Annotations: <none>
Status: Running
IP: 172.18.0.3
IPs:
IP: 172.18.0.3
Controlled By: ReplicationController/kubia
Containers:
kubia:
Container ID: docker://ec65afaeea2e8726530863981512165bec02ceb8e953a3d6575f6ea4ad7cc3f3
Image: 172.17.0.1:5000/kubia:v1
Image ID: docker-pullable://172.17.0.1:5000/kubia@sha256:0a9705988c08da5cc4fd535f40216a7b0ef89325b594ddb97ffcbd220c6731f1
...

通过kubectl set image rc/kubia kubia=172.17.0.1:5000/kubia:v2更新镜像。此时的应用程序并不会自动更新。当POD 异常或者手工删除以后RC 会自动拉起一个POD ,保证POD的副本数和RC 中配置的一致,此时新的POD 就是使用新的镜像创建应用,也就是说有的POD 使用新的镜像,有的POD 使用老的镜像。可以通过kubectl describe po查询到POD中容器的镜像版本不同。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
kubectl describe po
Name: kubia-c4cb9
Namespace: default
Priority: 0
Node: minikube/172.17.0.3
Start Time: Wed, 14 Oct 2020 20:29:56 +0800
Labels: app=kubia
Annotations: <none>
Status: Running
IP: 172.18.0.4
IPs:
IP: 172.18.0.4
Controlled By: ReplicationController/kubia
Containers:
kubia:
Container ID: docker://2b259af30a0c75987f027ac4516a7ea368774bbac4259a732f8141fdbcae376a
Image: 172.17.0.1:5000/kubia:v1
Image ID: docker-pullable://172.17.0.1:5000/kubia@sha256:0a9705988c08da5cc4fd535f40216a7b0ef89325b594ddb97ffcbd220c6731f1
Port: 3000/TCP
Host Port: 0/TCP
State: Running
Started: Wed, 14 Oct 2020 20:30:04 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-d2hsm (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-d2hsm:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-d2hsm
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m43s default-scheduler Successfully assigned default/kubia-c4cb9 to minikube
Normal Pulled 6m36s kubelet Container image "172.17.0.1:5000/kubia:v1" already present on machine
Normal Created 6m36s kubelet Created container kubia
Normal Started 6m35s kubelet Started container kubia


Name: kubia-s6822 ‹--自动使用新的镜像创建新的POD
Namespace: default
Priority: 0
Node: minikube/172.17.0.3
Start Time: Wed, 14 Oct 2020 20:35:57 +0800
Labels: app=kubia
Annotations: <none>
Status: Running
IP: 172.18.0.6
IPs:
IP: 172.18.0.6
Controlled By: ReplicationController/kubia
Containers:
kubia:
Container ID: docker://91fd664961c798256afbfd9b2e6cd47697a817f27803812da26e28d56212371e
Image: 172.17.0.1:5000/kubia:v2
Image ID: docker-pullable://172.17.0.1:5000/kubia@sha256:0709bbd6e3a34f306a16207b79b045e6a4bf33c22a3e7a88404166caee41e51f
Port: 3000/TCP
Host Port: 0/TCP
State: Running
Started: Wed, 14 Oct 2020 20:36:02 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-d2hsm (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-d2hsm:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-d2hsm
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 42s default-scheduler Successfully assigned default/kubia-s6822 to minikube
Normal Pulled 38s kubelet Container image "172.17.0.1:5000/kubia:v2" already present on machine
Normal Created 37s kubelet Created container kubia
Normal Started 37s kubelet Started container kubia


Name: kubia-wxj55
Namespace: default
Priority: 0
Node: minikube/172.17.0.3
Start Time: Wed, 14 Oct 2020 20:29:56 +0800
Labels: app=kubia
Annotations: <none>
Status: Running
IP: 172.18.0.2
IPs:
IP: 172.18.0.2
Controlled By: ReplicationController/kubia
Containers:
kubia:
Container ID: docker://a5195a7ec8573d429445f7c79218372abc887d360b3564c8659b600c236c0248
Image: 172.17.0.1:5000/kubia:v1
Image ID: docker-pullable://172.17.0.1:5000/kubia@sha256:0a9705988c08da5cc4fd535f40216a7b0ef89325b594ddb97ffcbd220c6731f1
Port: 3000/TCP
Host Port: 0/TCP
State: Running
Started: Wed, 14 Oct 2020 20:30:04 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-d2hsm (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-d2hsm:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-d2hsm
Optional: false
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 6m44s default-scheduler Successfully assigned default/kubia-wxj55 to minikube
Normal Pulled 6m36s kubelet Container image "172.17.0.1:5000/kubia:v1" already present on machine
Normal Created 6m36s kubelet Created container kubia
Normal Started 6m35s kubelet Started container kubia

使用ReplicationController部署应用,需要手工选择POD 逐一进行升级。实际部署应用过程中我们希望这个过程可以可控、且自动完成,这就需要通过更高级更高级的概念来部署应用。

使用Deployment部署应用

Kubernetes提供更高级的概念来实现应用的部署、滚动升级以及回滚。一个典型的kubernetes的应用会包含:POD、RepliciaSet以及Deployment。他们之间的关系如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment
metadata:
name: kubia
spec:
replicas: 3
selector:
matchLabels:
app: kubia
template:
metadata:
labels:
app: kubia
spec:
containers:
- name: kubia
image: 172.17.0.1:5000/kubia:v1

还是上面的例子,这次将ReplicationController的yaml文件中kinde替换城Deployment,并另存为kubia-deploymnent.yaml,使用kubectl create -f kubia-deployment.yaml重新部署应用,部署成功以后可以功过kubectl get po,rs,deployment查询部署的应用情况。

1
2
3
4
5
6
7
8
9
10
11
12
kubectl get po,rs,deployment
NAME READY STATUS RESTARTS AGE
pod/kubia-7fc889c9c9-b7b8f 1/1 Running 1 21h
pod/kubia-7fc889c9c9-lp7m8 1/1 Running 1 21h
pod/kubia-7fc889c9c9-qkz9w 1/1 Running 1 21h

NAME DESIRED CURRENT READY AGE
replicaset.apps/kubia-7fc889c9c9 3 3 3 21h

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kubia 3/3 3 3 21h

通过kubectl descibe po查询到POD到详细情况如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
kubectl describe po
Name: kubia-7fc889c9c9-b7b8f
Namespace: default
Priority: 0
Node: minikube/172.17.0.3
Start Time: Tue, 13 Oct 2020 22:44:19 +0800
Labels: app=kubia
pod-template-hash=7fc889c9c9
Annotations: <none>
Status: Running
IP: 172.18.0.2
IPs:
IP: 172.18.0.2
Controlled By: ReplicaSet/kubia-7fc889c9c9
Containers:
kubia:
Container ID: docker://aa524c986c27e53d12961173a5a0adf43a3554e13aeac5fc1c5cca083da09271
Image: 172.17.0.1:5000/kubia:v1 ‹-- 镜像版本是v1
Image ID: docker-pullable://172.17.0.1:5000/kubia@sha256:0a9705988c08da5cc4fd535f40216a7b0ef89325b594ddb97ffcbd220c6731f1
...

更新应用

  • 配置更新镜像

kubectl set image deployment/kubia kubia=172.17.0.1:5000/kubia:v2

设置完成以后deployment会自动滚动升级,可以通过kubectl rollout deployment/kubia status查询升级状态,此时查询应用部署的详情可以看到PO,RS更新中或者已经更新成功。kubectl get po,rs,deployment
其中存在2个rs,一个升级前的rs,一个是当前到rs。

1
2
3
4
5
6
7
8
9
10
11
12
13
kubectl get po,rs,deployment
NAME READY STATUS RESTARTS AGE
pod/kubia-7fc889c9c9-b7b8f 1/1 Running 1 21h
pod/kubia-7fc889c9c9-lp7m8 1/1 Running 1 21h
pod/kubia-7fc889c9c9-qkz9w 1/1 Running 1 21h
pod/kubia-84ddcd9474-bv8fl 0/1 ContainerCreating 0 3s ‹-- 新建POD

NAME DESIRED CURRENT READY AGE
replicaset.apps/kubia-7fc889c9c9 3 3 3 21h ‹-- 升级前的rs
replicaset.apps/kubia-84ddcd9474 1 1 0 4s ‹-- 当前的rs

NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/kubia 3/3 1 3 21h

查询POD详细信息,可以看到新建到POD已经更新为新到镜像。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
kubectl describe po kubia-84ddcd9474-bv8fl                                  ‹-- 新建POD
Name: kubia-84ddcd9474-bv8fl
Namespace: default
Priority: 0
Node: minikube/172.17.0.3
Start Time: Wed, 14 Oct 2020 20:19:12 +0800
Labels: app=kubia
pod-template-hash=84ddcd9474
Annotations: <none>
Status: Running
IP: 172.18.0.6
IPs:
IP: 172.18.0.6
Controlled By: ReplicaSet/kubia-84ddcd9474
Containers:
kubia:
Container ID: docker://3de190659e28bebcde082b287c7c4c434ab706c08654f6d1c7db3db455304508
Image: 172.17.0.1:5000/kubia:v2 ‹-- 镜像版本是v2
Image ID: docker-pullable://172.17.0.1:5000/kubia@sha256:0709bbd6e3a34f306a16207b79b045e6a4bf33c22a3e7a88404166caee41e51f

  • 管理升级

此时如果使用kubectl rollout undo deployment/kubia 即可全部回滚应用,可以通过kubectl rollout pause/resume/restart/history等控制滚动升级过程(如果测试过程中难以观察到升级过程,可以讲deployment中副本数量调高)。


此外,也可以使用StatefulSet部署有状态应用。StatefulSet和Deployment最大的区别是为每个副本POD实例提供店里存储,可以保证POD副本有固定的名字和主机,可以按照预期的顺序启停POD副本。

Kubernetes使用ConfigMap配置应用程序(二)

上一篇学习了通过args方式还是env方式都是将配置应用,配置参数硬编码在POD配置文件中,实际应用部署的过程中,我们希望配置参数和POD配置能够解藕,今天我们就看一下如何用ConfigMap配置应用。

创建一个ConfigMap

  • 使用命令行创建
1
kubectl create configmap fortune-configmap --from-literal=sleep-interval=60

创建成功以后可以通过kubectl命令查询configmap的配置。

kubectl get configmap fortune-configmap -o yaml
查询结果如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: v1
data:
sleep-interval: "60"
kind: ConfigMap
metadata:
creationTimestamp: "2020-09-29T12:29:40Z"
managedFields:
- apiVersion: v1
fieldsType: FieldsV1
fieldsV1:
f:data:
.: {}
f:sleep-interval: {}
manager: kubectl-create
operation: Update
time: "2020-09-29T12:29:40Z"
name: fortune-configmap
namespace: default
resourceVersion: "2434"
selfLink: /api/v1/namespaces/default/configmaps/fortune-configmap
uid: a6562e65-1431-47b1-b153-e4c270561a2c
  • 使用yaml文件创建

上述查询到信息将metadata中只保留名称就可以创建一个简单的ConfigMap配置文件,使用如下命令即可通过文件创建ConfigMap
kubectl create -f fortune-congfigmap.yaml

在POD文件中使用CongfigMap配置应用

  • 使用环境变量配置应用修改POD配置文件,使用ConfigMap配置env参数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
apiVersion: v1
kind: Pod
metadata:
name: fortune-env
labels:
app: fortune-env
spec:
containers:
- name: html-gen
image: 172.17.0.1:5000/fortune:env
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-configmap
key: sleep-interval
volumeMounts:
- name: html
mountPath: /var/htdocs
- name: log
mountPath: /var/log/fortune
- name: web-server
image: 172.17.0.1:500/nginx:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
- name: log-server
image: 172.17.0.1:5000/nginx:log
volumeMounts:
- name: log
mountPath: /usr/share/nginx/log
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: html
emptyDir: {}
- name: log
emptyDir: {}

重新创建PODkubectl create -f fortune-pod-env.yaml, 此时再查询fortune每个60秒更新一次。实际应用部署时,也可以修改ConfigMap的配置,当新新建POD时会使用新的ConfigMap值。

  • 使用参数配置应用

和使用环境变量配置POD类似,修改POD配置文件,使用ConfigMap配置args参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
apiVersion: v1
kind: Pod
metadata:
name: fortune-args
labels:
app: fortune-args
spec:
containers:
- name: html-gen
image: 172.17.0.1:5000/fortune:args
env:
- name: INTERVAL
valueFrom:
configMapKeyRef:
name: fortune-configmap
key: sleep-interval
args: [$(INTERVAL)]
volumeMounts:
- name: html
mountPath: /var/htdocs
- name: log
mountPath: /var/log/fortune
- name: web-server
image: 172.17.0.1:500/nginx:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
- name: log-server
image: 172.17.0.1:5000/nginx:log
volumeMounts:
- name: log
mountPath: /usr/share/nginx/log
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: html
emptyDir: {}
- name: log
emptyDir: {}

创建PODkubectl create -f fortune-pod-args.yaml, 此时查询fortune每个60秒更新一次。

此时,如果删除旧的ConfigMap,重新配置一个新的ConfigMap,再同时删除frotune-env pod和fortune-args pod并重新新建POD时会使用新的ConfigMap值。

ConfigMap可以配置的资源

从文件、文件夹和字符创建的ConfigMap

Kubernetes使用ConfigMap配置应用程序(一)

传统的应用程序在部署时往往需要通过命令行参数、环境变量、配置文件等方式配置应用程序。Kubernetes应用程序可以通过ConfigMap和Secret来配置应用程序。ConfigMap和Secret的区别主要是Secret用于敏感数据配置,数据在Kubernetes中是加密存储的。

选择ConfigMap和Secret的原则比较简单:

  • 非敏感数据则使用ConfigMap配置;
  • 敏感数据使用Secret配置;
  • 如果既有敏感数据又有非敏感数据则使用Secret配置。

ConfigMap和Secret使用方式类似,这里主要描述ConfigMap的使用方式。

这次还是以fortune应用程序为例,通过ConfigMap向fortune传递参数调整程序刷新的时间间隔。首先我看一下不借助ConfigMap我们如何通过命令参数和环境变量配置应用。

1.使用命令参数配置应用

修改fortune镜像,增加间隔参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#! /bin/bash
trap "exit" SIGINT
INTERVAL=$1

mkdir /var/htdocs
mkdir /var/fortune

echo Configured to generate new fortune every $INTERVAL seconds.

while :
do
echo $(date) writing fortune to /var/htdocs/index.html >> /var/log/fortune/$(date +%Y-%m-%d).log
/usr/games/fortune > /var/htdocs/index.html

sleep $INTERVAL
done
  • 修改Dockerfile增加默认参数
1
2
3
4
5
6
FROM ubuntu:latest
RUN apt update ; apt install -y fortune
ADD fortuneloop.sh /bin/fortuneloop.sh

ENTRYPOINT ["/bin/fortuneloop.sh"]
CMD ["10"]

重新制作镜像:docker build -t 172.17.0.1:5000/fortune:args .,并推送本地镜像仓库

  • 本地运行镜像测试
1
2
docker run --name fortune-args -it 172.17.0.1:5000/fortune:args 15
Configured to generate new fortune every 15 seconds.

在POD中使用args覆盖容器参数

  • 修改POD配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- name: html-gen
image: 172.17.0.1:5000/fortune:args
args: ["30"]
volumeMounts:
- name: html
mountPath: /var/htdocs
- name: log
mountPath: /var/log/fortune
- name: web-server
image: 172.17.0.1:500/nginx:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
- name: log-server
image: 172.17.0.1:5000/nginx:log
volumeMounts:
- name: log
mountPath: /usr/share/nginx/log
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: html
emptyDir: {}
- name: log
emptyDir: {}

这样重新创建POD即可看到应用参数更新成"30"秒。

2.使用环境变量配置应用

修改fortune镜像,增加间隔环境变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#! /bin/bash
trap "exit" SIGINT
mkdir /var/htdocs
mkdir /var/fortune

echo Configured to generate new fortune every $INTERVAL seconds.

while :
do
echo $(date) writing fortune to /var/htdocs/index.html >> /var/log/fortune/$(date +%Y-%m-%d).log
/usr/games/fortune > /var/htdocs/index.html

sleep $INTERVAL
done
  • 修改Dockerfile增加默认参数
1
2
3
4
5
FROM ubuntu:latest
RUN apt update ; apt install -y fortune
ADD fortuneloop.sh /bin/fortuneloop.sh

ENTRYPOINT ["/bin/fortuneloop.sh"]

重新制作镜像:docker build -t 172.17.0.1:5000/fortune:env .,并推送本地镜像仓库

在POD中使用env覆盖容器参数

  • 修改POD配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- name: html-gen
image: 172.17.0.1:5000/fortune:env
env:
- name: INTERVAL
value: "45"
volumeMounts:
- name: html
mountPath: /var/htdocs
- name: log
mountPath: /var/log/fortune
- name: web-server
image: 172.17.0.1:500/nginx:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
- name: log-server
image: 172.17.0.1:5000/nginx:log
volumeMounts:
- name: log
mountPath: /usr/share/nginx/log
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: html
emptyDir: {}
- name: log
emptyDir: {}

这样重新创建POD即可看到应用参数更新成"45"秒。

上述两种方式,无论时通过args方式还是env方式都是将配置参数硬编码在POD配置文件中。实际应用部署的过程中,我们希望配置参数和POD配置能够解藕,这个就需要用到Kubernetes提供的ConfigMap来实现。

修改docker hub上的官方镜像

之前一直有个疑问,如果要在同一个Kubernetes的POD中部署两个系统镜像的容器,两个容器岂不是会有资源(网络端口号,文件等)冲突。在尝试在Kubernetes挂载不同的存储时就遇到同一个nginx镜像部署在同一个POD中,第二个POD始终失败的问题,查看日志也提示尝试多次终止了容器。猜测应该是在同一个POD中端口冲突导致第二个容器启动失败,于是修改官方nginx镜像的端口号成功在一个POD中启动了两个nginx容器。

具体操作如下:

从dokcer hub官方下载nginx:alpine镜像

docker pull nginx:alpine

查看镜像中的默认配置

1
2
docker run -it --name nginx  nginx:alpine /bin/sh
cat /etc/nginx/nginx.conf

修改官方镜像

  • 根据官方镜像修改端口号及默认目录
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
user  nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;


events {
worker_connections 1024;
}


http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;

sendfile on;
#tcp_nopush on;

keepalive_timeout 65;

#gzip on;

server {
listen 8080;
listen [::]:8080;
server_name localhost;

#charset koi8-r;
#access_log /var/log/nginx/host.access.log main;

location / {
root /usr/share/nginx/log;
# index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}

}
  • 新的dockerfile
1
2
3
4
FROM nginx:alpine
RUN mkdir -p /usr/share/nginx/log
ADD index.html /usr/share/nginx/log/index.html
COPY nginx.conf /etc/nginx/nginx.conf
  • 构建新的镜像

docker build -t nginx:log .

本地测试成功以后就可以推送到自己的镜像仓库了:)。

Kubernetes挂载存储

示例说明

为演示在Kubernetes挂载存储以下面为例:

  • fortune进程利用fortune游戏每10秒钟更新一次html文档;并将更新过程钟写入日志。

  • web-server进程使用nginx作为web服务器向外提供服务,客户展示fortune生成的html文件。

  • log-server进程使用nginx作为服务器向外提供服务,可以查询fortune日志。

分别将上述进程部署到不同的容器中,容器间通过挂载emptyDir卷共享信息。

测试代码

  • fortune程序
1
2
3
4
5
6
7
8
9
10
11
12
#! /bin/bash
trap "exit" SIGINT
mkdir /var/htdocs
mkdir /var/fortune

while :
do
echo $(date) writing fortune to /var/htdocs/index.html >> /var/log/fortune/$(date +%Y-%m-%d).log
/usr/games/fortune > /var/htdocs/index.html

sleep 10
done

每10秒钟生成一次html文件,并记录生成日志

  • fortune的dockerfile
1
2
3
4
5
FROM ubuntu:latest
RUN apt update ; apt install -y fortune
ADD fortuneloop.sh /bin/fortuneloop.sh

ENTRYPOINT /bin/fortuneloop.sh
  • 将三个示例容器部署到一个POD中
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
apiVersion: v1
kind: Pod
metadata:
name: fortune
labels:
app: fortune
spec:
containers:
- name: html-gen
image: 172.17.0.1:5000/fortune
volumeMounts:
- name: html
mountPath: /var/htdocs
- name: log
mountPath: /var/log/fortune
- name: web-server
image: 172.17.0.1:500/nginx:alpine
volumeMounts:
- name: html
mountPath: /usr/share/nginx/html
readOnly: true
ports:
- containerPort: 80
protocol: TCP
- name: log-server
image: 172.17.0.1:5000/nginx:log
volumeMounts:
- name: log
mountPath: /usr/share/nginx/log
readOnly: true
ports:
- containerPort: 8080
protocol: TCP
volumes:
- name: html
emptyDir: {}
- name: log
emptyDir: {}

nginx:log源于nginx:alpine镜像,只是将nginx默认80端口修改成8080端口,将默认的html root目录修改成/usr/share/nginx/log目录,具体修改方法下次在详细讲。

  • 建立一个NodePort类型的Service对外提供web服务
1
2
3
4
5
6
7
8
9
10
11
12
13
kind: Service
apiVersion: v1
metadata:
name: fortune-web-nodeport
spec:
selector:
app: fortune
type: NodePort
ports:
- port: 8088
targetPort: 80
nodePort: 30157

注意selector实际是按照POD中容器标签进行选择的,因此该信息必须和POD中设置的标签保持一致;
targetPort和容器端口一致,nginx:alpine默认端口是80端口

  • 建立一个NodePort类型的Service对外提供log服务
1
2
3
4
5
6
7
8
9
10
11
12
kind: Service
apiVersion: v1
metadata:
name: fortune-log-nodeport
spec:
selector:
app: fortune
type: NodePort
ports:
- port: 8090
targetPort: 8080
nodePort: 30159

注意selector实际是按照POD中容器标签进行选择的,因此该信息必须和POD中设置的标签保持一致;
targetPort和容器端口一致,nginx:log默认端口是8080端口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: fortune-ingress
spec:
rules:
- host: fortune-web.local.com
http:
paths:
- path: /
backend:
serviceName: fortune-web-nodeport
servicePort: 8088
- host: fortune-log.local.com
http:
paths:
- path: /
backend:
serviceName: fortune-log-nodeport
servicePort: 8090

通过Ingress对外提供访问策略,分别根据不同的域名选择到不同的服务中。新版本的Kubernetes提供了新的网络策略接口,在后续文章中详细测试。

  • 配置域名和IP地址

在minikube中创建ingress后可以通过:kubectl get ingress 查询ingress信息,该信息中包含了域名和IP地址的对应信息,在/etc/hosts中配置该信息即可在本机通过域名访问服务。

测试结果

  • 查询资源信息
  • 修改hosts文件
  • 访问web和log服务

Kubernetes将服务暴露给外部方式

kubernets集群内部的服务可以直接环境变量、内部DNS等方式被发现,并在集群内部提供服务。如何将Kubernetes的服务暴露给外部客户端呢?
Kubernetes提供以下集中方式将服务暴露给开外部客户端:

通过NodePort暴露服务

顾名思义,将服务类型设置成NodePort方式,Kubernetes会在集群每个节点上打开一个端口,将该端口的流量转发到服务的POD。

通过负载均衡器暴露

负载均衡方式实际是NodePort方式的增强,将服务类型设置成LoadBalancer方式实际是通过云基础架构提供的负载均衡器,将流量转发到集群内部的NodePort上。

通过Ingress暴露

Ingress是Kubernetes一种资源,通过类似LoadBalancer类似的能力,区别在于每个LoadBalancer都需要一个独立的公网IP,而Ingress只需要一个公网IP即可根据规则将流量转发到对应的服务。