kubernetes 基础环境搭建及问题记录

初衷

  • 由于公司采用的是微服务的服务架构,这段时间运维(人少,只有一位大佬呀心疼一波)那边有一丢丢压力,我想去帮助一下。So,正好借此机会去学习了kubenetes的搭建,并写下了这一份搭建手册(当然自己也想掌握搭建测试环境这一项技能哈哈哈哈😄)。

安装前期准备工作

环境准备 ubuntu 16.04.5 server x64 lts

1
2
3
proxy   http://118.25.xxx.xxx:8118  https://118.25.xxx.xxx:8118
master 172.16.147.129 master.bruce.com
node1 172.16.147.130 node1.bruce.com
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 关闭缓存 
swapoff -a

# 关闭防火墙
ufw disable

# 查看iptables规则
iptables -S -t filter

# 允许所有端口通信
iptables -F # 重置iptables规则
iptables -P OUTPUT ACCEPT
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT

本文中用到的插件版本

安装必备的基础工具

1
sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common

安装docker

此次docker安装 使用 apt install docker-compose方法安装 docker版本为 17.03.2-ce(安装的版本为当前时间下的最新版本) 也可以使用下面的方法进行安装docker

1
2
3
4
5
6
7
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -  #添加软件源验证密钥
sudo add-apt-repository 'deb https://apt.dockerproject.org/repo ubuntu-xenial main' #添加软件源
sudo apt-get update #更新软件源
sudo apt-cache policy docker-engine #列出Docker-engine版本
sudo apt-get -y install docker-engine=[VERSION] --allow-unauthenticated #选择版本[VERSION]进行安装,例如 docker-engine=1.13.1-0~ubuntu-xenial
sudo apt-get -y install docker-engine=1.13.1-0~ubuntu-xenial --allow-unauthenticated
systemctl status docker #验证Docker服务
1
2
3
4
5
6
sudo vim /etc/systemd/system/multi-user.target.wants/docker.service   fd:// --registry-mirror={加速器地址}   #添加docker下载镜像加速
sudo mkdir -p /etc/systemd/system/docker.service.d #配置docker翻墙
sudo vim /etc/systemd/system/docker.service.d/https-proxy.conf #配置docker翻墙

[Service]
Environment="HTTP_PROXY=http://xxx:xxx/" "HTTPS_PROXY=https://xxx:xxx/" "NO_PROXY=localhost,127.0.0.1,*.mirror.aliyuncs.com" #*.mirror.aliyuncs.com可以替换自己的加速镜像地址
1
2
3
4
sudo systemctl daemon-reload    #重新加载配置文件
sudo systemctl restart docker #重启docker服务
systemctl show --property=Environment docker #查看docker配置的环境信息
sudo usermod -aG docker $(whoami) #将当前用户加入docker用户组

安装kubernetes环境

1
2
3
4
5
6
7
*环境版本信息* 
kubeadm 1.8.2
kubectl 1.8.2
kubelet 1.8.2
kubernetes-dashboard 1.10.0
calico 3.1
docker 17.03.2-ce

切换su用户

1
sudo su

安装kubernetes软件源密钥

1
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -  #安装kubernetes软件源密钥

安装kubernetes软件源

1
2
3
4
5
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF

apt-get update #添加并更新软件源

部署master节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装kubelet kubectl kubeadm 
apt-get install -y kubelet=1.8.2-00
apt-get install -y kubectl=1.8.2-00
apt-get install -y kubeadm=1.8.2-00

# 安装完成后修改部分属性,保证kubelet可以正常运行
sudo vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
在KUBELET_KUBECONFIG_ARGS中添加参数:--fail-swap-on=false

# 初始化master节点
sudo kubeadm init --kubernetes-version=v1.10.0 --token-ttl=0 --skip-preflight-checks --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address={master-ip}

--kubernetes-version=v1.10.0 # 制定kubernetes版本
--token-ttl=0 # ttl(time to live)token不会过期
--pod-network-cidr=192.168.0.0/16 # pod网络,采用calico网络部署,则需要calico有效的网段
--apiserver-advertise-address={master-ip} # 制定api-server注册地址
--skip-preflight-checks # 解决一个kubelet目录不空的小bug
1
2
3
4
5
6
7
# 初始化网络
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 记录子节点加入集群的命令
kubeadm join --token 0125ca.fe842bbac676cb16 172.16.147.129:6443 --discovery-token-ca-cert-hash sha256:1c65574f4431be8ea7be764eb7e56643776bbabaae24f85e1819545d70d9698d

部署node节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 安装kubelet kubectl kubeadm
# 安装完成后 使用kubeadm join 命令加入集群
sudo kubeadm join --token [token] --skip-preflight-checks --discovery-token-ca-cert-hash sha256:[CA key] [kubemaster_host]:[kubemaster_ip]
# 获取kubeadm join命令最简单的办法,在kubeadm init 后拿到给出的kubeadm join命令存储下来即可
# 手动获取
[token]获取
1. kubeadm token list or kubeadm token create
[CA key]获取
2. openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'

# 子节点初始化网络
mkdir -p $HOME/.kube
sudo scp {master-server}:/etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

# 修改子节点ROLES
kubectl label node <node-name> node-role.kubernetes.io/node=node

安装kubernetes dashboard

1
2
# 下载kubernetes-dashboard yaml文件 
wget https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

修改type为NodePort

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 增加 type: NodePort (暴露端口供外部访问)
# ------------------- Dashboard Service ------------------- #
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
ports:
- port: 443
targetPort: 8443
selector:
k8s-app: kubernetes-dashboard

准备kubernetes-dashboard-rbac.yaml认证文件

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: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-admin
namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: kubernetes-dashboard-admin
labels:
k8s-app: kubernetes-dashboard
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard-admin
namespace: kube-system

部署 kubernetes-dashboard

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 部署
kubectl apply -f kubernetes-dashboard.yaml kubernetes-dashboard-rbac.yaml

# 获取kubernete-dashboard-admin的token
kubectl -n kube-system get secret | grep kubernetes-dashboard-admin
kubectl describe -n kube-system secret/kubernetes-dashboard-admin-token-xxxxx

# 记录Token
eyJhbGciOiJSUzI1NiIsImtpZCI6IiJ9.eyJpc3MiOiJrdWJlcm5ldGVzL3NlcnZpY2VhY2NvdW50Iiwia3ViZXJuZXRlcy5pby9zZXJ2aWNlYWNjb3VudC9uYW1lc3BhY2UiOiJrdWJlLXN5c3RlbSIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VjcmV0Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC1hZG1pbi10b2tlbi1mZzlwbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50Lm5hbWUiOiJrdWJlcm5ldGVzLWRhc2hib2FyZC1hZG1pbiIsImt1YmVybmV0ZXMuaW8vc2VydmljZWFjY291bnQvc2VydmljZS1hY2NvdW50LnVpZCI6IjgzMWM5ZGU3LWVjZTItMTFlOC1hZTE5LTAwMGMyOTcwZWQ0YyIsInN1YiI6InN5c3RlbTpzZXJ2aWNlYWNjb3VudDprdWJlLXN5c3RlbTprdWJlcm5ldGVzLWRhc2hib2FyZC1hZG1pbiJ9.vUPajZnjUic2GQTt-TzQPaVqy1_OiQyc1ZB_7qsqUMm_6OOTbYod7qDXQ5LzJbiMddD8fEwyH8nwMMNoLhGYnesi_DXgqy_GwMlC3tJDdjWKr6fINW8nHpp08SF-VcvOPgpcHaVsmX0ozLkbxaK9gLDv7pevE8tY37b-EjmiiRGSYU9gecZSmB_MqdQyN3oG83cl60IyszQHobZVP4T67pi7NnotDfmFRhrWcJ-TLqtmd3PTKBrNyYrtrC8L3YIEY1ZWkjSrhK7Ow3CPIlRUOSwiHKzyYinoHyAG26byEKzi36tw_yLeZKlaRZKeN4kKOcjApf-vUv8kAaUoof7KHg

# 获取随机生成的NodePort并记录
kubectl get svc -n kube-system # Kubernetes Dashboard NodePort: 31230

# 使用刚才获取到的token登录 kubernetes-dashboard
'https://{cluster ip}:{nodeport}/#!/login'
'https://master.bruce.com:31230/#!/login'

安装监控插件 heapster

1
2
3
4
5
6
7
8
9
10
ref: https://github.com/kubernetes/heapster

# 修改grafana中的NodePort,并指定NodePort 30081(与dashboard一致)
/heapster/deploy/kube-config/influxdb/grafana.yaml

# 部署步骤
kubectl apply -f influxdb/
kubectl apply -f rbac/
# 记录grafana的地址
'http://master.bruce.com:30081'

master节点参与工作负载

master节点默认不参与工作负载的原因

  • 使用kubeadm初始化的集群,出于安全考虑Pod不会被调度到Master Node上,也就是说Master Node不参与工作负载。这是因为当前的master节点node1被打上了node-role.kubernetes.io/master:NoSchedule的污点;由于此处是用来搭建自己测试使用的环境,所以放开该限制可以提高资源利用率。

去掉master节点上的污点

1
2
kubectl describe node | grep Taint --> Taints: node-role.kubernetes.io/master:NoSchedule
kubectl taint nodes master node-role.kubernetes.io/master- --> node "master" untainted

问题记录

1

1
2
3
4
Q. Heapster cannot dial API server
A.
Changed the line in heapster.yaml to this:
" - --source=kubernetes.summary_api:https://kubernetes.default"

2

1
2
3
4
5
6
7
8
9
10
11
12
Q. 如果碰到nodePort无法访问的情况,只能通过pod所在节点的ip进行访问,很大可能是iptables的原因(新版本的docker 会将FORWORD的请求默认DROP)
A1.
vi /etc/sysctl.conf net.ipv4.ip_forward=1
/sbin/sysctl -p
A2.
iptables -I FORWARD -s 0.0.0.0/0 -d 0.0.0.0/0 -j ACCEPT
由于docker部分版本重启可能修改默认的iptables的FORWORD的默认属性,下列操作会保证FROWORD的请求默认为ACCEPT,从而避免FORWORD的请求被DROP导致pod访问出现问题。

vi /etc/systemd/system/multi-user.target.wants/docker.service -->
增加
[Service]
ExecStartPost=/sbin/iptables -I FORWARD -s 0.0.0.0/0 -d 0.0.0.0/0 -j ACCEPT

3

1
2
3
4
5
6
7
8
9
Q. master上的pod访问不到node上的pod,ip ping不通
A.

ip route #配置路由器静态路由的命令,可以查看机器上的网卡路由信息
tcpdump -i {网卡名称}
tcpdump -i cali43e7284e19c

每个pod都对应一个ip和一个网卡地址,选取master上的pod1和node上的pod2,使用tcpdump抓包,在pod1中ping pod2,查看网络信息,发现pod1上的网络信息存在问题
`09:34:46.809745 ARP, Reply 169.254.1.1 is-at ee:ee:ee:ee:ee:ee (oui Unknown), length 28`
1
2
google后发现问题解决方案
'https://docs.projectcalico.org/v3.2/reference/node/configuration#ip-autodetection-methods'
1
2
3
4
在calico.yaml文件中加上一下属性,重新apply即可
# https://github.com/projectcalico/calico/issues/2042#issuecomment-408488357
- name: IP_AUTODETECTION_METHOD
value: "interface=ens33" #指定网卡

补充

如何使用secret

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 创建tls.crt tls.key 并生成 k8s secret,使用secret
# tls类型的secret

openssl genrsa -out tls.key 2048
openssl req -new -x509 -key tls.key -out tls.crt -subj /C=CN/ST=Shanghai/L=Shanghai/O=Devops/CN={service hosts}
kubectl create secret tls {secret-name} --cert={tls.crt-location} --key={tls.key-location} -n {namespace}

kubectl explian ingress.spec.tls
spec:
tls:
- hosts:
- xx.xx.com
secretName: {secret-name}

# generic类型的secret
## htpasswd生成的密码
htpasswd -c auth kubedashboardauth # htpasswd -c auth {username}
kubectl create secret generic kubedashboard-auth-secret -n kube-system --from-file auth
kubectl get secret kubedashboard-auth-secret -o yaml -n kube-system

## 明文密码
kubectl create secret generic kubedashboard-auth-secret --from-literal=username=bruce --from-literal=password=123456 -n kube-system

Ingress暴露Https链接时遇到的问题

ingress暴露https连接时,需要添加一个支持https的annotation,否则服务会报错 tls: first record does not look like a TLS handshake

  • 在ingress的yaml文件中添加 nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" 即可解决。

  • Ingress Annotation Refer
    https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/

ERP搭建(java服务)启动时redis无法连接

  • 修改/etc/redis/6379.conf中的配置,使redis监听所有的ip段,增加bind 0.0.0.0即可。

Thanks For Watching!