Docker HAProxy使用示例

1. 准备Docker HAProxy基础环境:

1
2
3
docker pull haproxy:1.6.5
mkdir haproxy
cd haproxy

2. 编写HAProxy的配置文件:

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
cat <<EOF > haproxy.cfg
global
log 127.0.0.1 local0 # 日志输出配置,所有日志都记录在本机,通过local0输出
maxconn 4096 # 最大连接数
tune.ssl.default-dh-param 2048
chroot /usr/local/sbin # 改变当前工作目录
daemon # 以后台形式运行HAProxy
nbproc 4 # 启动4个HAProxy实例
pidfile /usr/local/sbin/haproxy.pid # pid文件位置
defaults
log 127.0.0.1 local3 # 日志文件的输出定向
mode http # { tcp|http|health } 设定启动实例的协议类型
option dontlognull # 保证HAProxy不记录上级负载均衡发送过来的用于检测状态没有数据的心跳包
option redispatch # 当serverId对应的服务器挂掉后,强制定向到其他健康的服务器
retries 2 # 重试两次连接失败就认为服务器不可用,主要通过后面的check检查
maxconn 2000 # 最大连接数
balance roundrobin # 负载均衡算法,roundrobin表示轮询,source表示按照IP
timeout connect 5000ms # 连接超时时间
timeout client 50000ms # 客户端连接超时时间
timeout server 50000ms # 服务器端连接超时时间
errorfile 400 /usr/local/etc/haproxy/errors/400.http
errorfile 403 /usr/local/etc/haproxy/errors/403.http
errorfile 408 /usr/local/etc/haproxy/errors/408.http
errorfile 500 /usr/local/etc/haproxy/errors/500.http
errorfile 502 /usr/local/etc/haproxy/errors/502.http
errorfile 503 /usr/local/etc/haproxy/errors/503.http
errorfile 504 /usr/local/etc/haproxy/errors/504.http
balance source

frontend http_frontend
bind *:80
mode http

default_backend server_harbor_backend

backend server_backend
mode http
...
server s1 192.168.86.128:31451
server s2 192.168.86.129:31451
server s3 192.168.86.130:31451
...

EOF

注意事项:宿主机的80端口未被占用;根据需要配置server_backend中的使用标记(…)圈上的部分。

3. 使用Docker镜像启动HAProxy容器:

1
docker run -d -p 80:80 --name haproxy -v `pwd`/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg haproxy:1.6.5

容器标签使用小记

docker cli使用举例

1
2
3
4
5
docker ps -a --filter "label=org.hyperledger.fabric.chaincode.id.name=test-chaincode" --filter "label=org.hyperledger.fabric.chaincode.id.version=v0.0.1"

或者

docker ps -a -f "label=org.hyperledger.fabric.chaincode.id.name=test-chaincode" -f "label=org.hyperledger.fabric.chaincode.id.version=v0.0.1"

如下图所示:

docker_label

docker client go编码示例

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
...
import (
"github.com/docker/docker/api/types"

"github.com/docker/docker/api/types/filters"
)
...
...
flagArgs := []string{
fmt.Sprintf("label=%s=%s", ChainCodeNameLabelKey, contractName), // "label=org.hyperledger.fabric.chaincode.id.name=wx-hy001"
fmt.Sprintf("label=%s=%s", ChainCodeVersionLabelKey, contractVersion), // "label=org.hyperledger.fabric.chaincode.id.version=1.2.0"
}
args := filters.NewArgs()
for i := range flagArgs {
args, err = filters.ParseFlag(flagArgs[i], args)
if err != nil {
glog.Error(err)
return contractChainCodes, err
}
}
containerList, err := cli.ContainerList(types.ContainerListOptions{
Filters: args,
})
if err != nil {
glog.Error(err)
return contractChainCodes, err
}
for j := 0; j < len(containerList); j++ {
container := containerList[j]
containerId := container.ID
containerName := container.Names[0][1 : ]
contractChainCode := module.ContractChainCode{
ContainerId: containerId,
ContainerName: containerName,
ContainerHost: hostIP,
}
contractChainCodes = append(contractChainCodes, contractChainCode)
}
...

如下图所示:

docker_label

kubernetes cli使用举例

1
2
3
4
5
kubectl get pod --all-namespaces -o wide -l baas.yonghui.cn/network-name=test-network

或者

kubectl get pod --all-namespaces -o wide -l baas.yonghui.cn/network-name=test-network,baas.yonghui.cn/network-component=peer

如下图所示:

kubernetes_label

kubernetes client go编码示例

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
...
import (
module "yonghui.cn/blockchain/yhbkas/module/network"
pkglabels "k8s.io/apimachinery/pkg/labels"
)
...
...
networkNameKey := string(sc.NetworkNameKey)
labels := map[string]string{
networkNameKey: networkName,
}
selector := pkglabels.FormatLabels(labels)
opts := metav1.ListOptions{
LabelSelector: selector,
}

podList, err := clientSet.CoreV1().Pods(metav1.NamespaceAll).List(opts)
if err != nil {
return module.GetNetworkComponentsResponse{
CommonResponse: module.CommonResponse{
Status: http.StatusInternalServerError,
Message: "GetNetworkComponents unsuccessfully.",
},
NetworkComponents: networkComponents,
}
}

for i := 0; i < len(podList.Items); i++ {
pod := podList.Items[i]
podContainers := make([]module.PodContainer, 0)
containers := pod.Spec.Containers
for j := 0; j < len(containers); j++ {
container := containers[j]
podContainer := module.PodContainer{
Name: container.Name,
}
podContainers = append(podContainers, podContainer)
}
labels := pod.Labels
componentTypeKey := string(sc.NetworkComponentTypeKey)
componentTypeValue := labels[componentTypeKey]
networkComponent := module.NetworkComponent{
Id: string(pod.UID),
Name: pod.Name,
Namespace: pod.Namespace,
Containers: podContainers,
Role: componentTypeValue,
}
networkComponents = append(networkComponents, networkComponent)
}
...

如下图所示:

kubernetes_label

Kubeadm安装Kubernetes之宿主机的相关参数修改

Kubeadm安装Kubernetes之宿主机的相关参数修改

1. ulimit -n 参数修改永久生效

1
2
3
4
cat <<EOF >  /etc/security/limits.d/k8s.conf
* hard nofile 65536
* soft nofile 65536
EOF

参考资料:
https://www.aliyun.com/jiaocheng/208647.html
https://www.aliyun.com/jiaocheng/124954.html
https://www.cnblogs.com/xuexiaohun/articles/6233430.html
https://my.oschina.net/jxcdwangtao/blog/1621106

2. 通过sysctl修改的相关内核参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

vm.swappiness = 0
net.ipv4.ip_forward = 1

net.ipv4.tcp_timestamps = 1
net.ipv4.tcp_tw_recycle = 1

net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_tw_resue = 1
EOF

sysctl --system

Docker容器的时区设置

Docker容器的时区设置,一直以来都是个简单而且重要的问题。下面笔者以CentOS 7.5.1804作为容器宿主机为例,分别介绍如何在原生Docker容器和Kubernetes的Pod中正确设置时区。

Node设置正确时区(以CentOS 7.5.1804 为例)

1
2
3
timedatectl list-timezones
timedatectl set-timezone Asia/Shanghai
timedatectl status | grep 'Time zone'

提示:这里相当于为Docker Container和Kubernetes Pod的宿主机设置正确的时区,需要优先配置完成。

Docker Container 与 Node同步时区设置

1
docker run -it -v /etc/localtime:/etc/localtime --rm alpine:3.8 /bin/sh

提示:上述命令注意-v参数的部分。
总结:经测试验证,alpine:3.8、centos:7.5.1804和ubuntu:16.04处理方式相同。

Kubernetes Pod 与 Node同步时区设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: v1
kind: Pod
metadata:
name: alpine
labels:
app: alpine
spec:
containers:
- image: alpine:3.8
imagePullPolicy: IfNotPresent
name: alpine
command:
- sleep
- "3600"
volumeMounts:
- name: tz-config
mountPath: /etc/localtime
readOnly: true
restartPolicy: Always
volumes:
- name: tz-config
hostPath:
path: /etc/localtime

提示:上述YAML注意volumes和volumeMounts部分。
总结:经测试验证,alpine:3.8、centos:7.5.1804和ubuntu:16.04处理方式相同。

Docker Container 和 Kubernetes Pod 通用 与 Node同步时区设置

该方式在需要构建Docker Image的时候,即修改Docker Image的默认时区设置。

Alpine Linux 3.8 Dockerfile Example

1
2
3
4
5
6
FROM alpine:3.8

MAINTAINER wangxin_0611@126.com

RUN apk --no-cache add tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

Ubuntu Linux 16.04 Dockerfile Example

1
2
3
4
5
6
7
FROM ubuntu:16.04

MAINTAINER wangxin_0611@126.com

RUN apt-get update && \
apt-get install -y tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

CenOS Linux 7.5.1804 Dockerfile Example

1
2
3
4
5
FROM centos:7.5.1804

MAINTAINER wangxin_0611@126.com

RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime

参考资料:
https://blog.csdn.net/qq_34924407/article/details/82057080
https://blog.csdn.net/u013201439/article/details/79436413