kubernetes+calico+nfs環境部署
原作者 張偉@天雲軟件,轉載請註明出處
主機說明:
- 系統版本:centos7.2,Linux kernel 3.10.0及以上版本。
- 系統規格:>=4CPU,>=4GRAM,120G磁盤(使用lvm管理,可動態擴容)。
主機規劃:
角色 | 主機名 | IP | 說明 |
---|---|---|---|
master,etcd | master | 172.16.10.2 | etcd,kubernetes(apiserver,scheduler,controller-manager),calico |
minion | minion1 | 172.16.10.3 | kubernetes(kubelet,proxy),docker,calico |
minion | minion2 | 172.16.10.4 | kubernetes(kubelet,proxy),docker,calico |
registry | registry | 172.16.10.5 | registry |
nfsserver | nfsserver | 172.16.10.6 | nfs-server |
軟件:
- etcd v2.2.5
- docker v1.9.1
- kubernetes二進制包(安裝完成後可替換二進制包進行升級):
- kubectl v1.2.0
- kubelet v1.2.0
- kube-proxy v1.2.0
- kube-scheduler v1.2.0
- kube-controller-manager v1.2.0
- kube-apiserver v1.2.0
- registry.access.redhat.com/rhel7/pod-infrastructure:latest(鏡像)
- calico:
- calicoctl v0.18.0
- calico/node:v0.18.0 (鏡像)
- calico v1.1.0
- calico-ipam v1.1.0
- calico/k8s-policy-agent:v0.1.2 (鏡像)
- policy
- easyrsa3
安裝kubernetes集羣
1.準備安裝源
建議使用阿里源替換系統自帶的源
配置kubernetes安裝源
關閉selinux: setenforce 0
2.安裝kubernetes master節點
yum install kubernetes etcd -y 安裝kubernetes的所有服務。
1)配置crt通信證書
1.1) 配置apiserver crt證書:
下載easyrsa3:
curl -L -O https://storage.googleapis.com/kubernetes-release/easy-rsa/easy-rsa.tar.gz
tar xzf easy-rsa.tar.gz
cd easy-rsa-master/easyrsa3
./easyrsa init-pki
創建CA:
./easyrsa --batch "--req-cn=${MASTER_IP}@`date +%s`" build-ca nopass (如果要使用默認的service訪問kubernetes集羣,使用--req-cn=*)
生成服務使用的cert和key:
./easyrsa --subject-alt-name="IP:${MASTER_IP}" build-server-full kubernetes-master nopass(如果要使用默認的service訪問kubernetes集羣,要在IP後邊配置service的IP:IP:${MASTER_IP},IP:${SERVICE_IP})*
mkdir -p /srv/kubernetes
cp pki/ca.crt /srv/kubernetes/
cp pki/issued/kubernetes-master.crt /srv/kubernetes/server.cert
cp pki/issued/kubernetes-master.key /srv/kubernetes/server.key
1.2)配置ServiceAccount:
openssl genrsa -out /srv/kubernetes/serviceaccount.key 2048
chmod +x /srv/kubernetes/*
2)配置etcd服務
vi /etc/etcd/etcd.conf
修改etcd監聽的網卡和端口,使服務能夠在集羣內訪問。
systemctl enable etcd
systemctl restart etcd
3)配置apiserver
vi /etc/kubernetes/config
將KUBE_MASTER的值修改爲正確的IP地址。
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"
# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"
# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=true"
# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://master:8080"
vi /etc/kubernetes/apiserver
修改apiserver監聽的網卡和端口,並配置使用的etcd集羣。注意增加apiserver的證書設置。
# The address on the local server to listen to.
KUBE_API_ADDRESS="--insecure-bind-address=0.0.0.0"
# The port on the local server to listen on.
# KUBE_API_PORT="--port=8080"
KUBE_API_PORT="--insecure-port=8080"
# Port minions listen on
# KUBELET_PORT="--kubelet-port=10250"
# Comma separated list of nodes in the etcd cluster
KUBE_ETCD_SERVERS="--etcd-servers=http://master:2379"
# Address range to use for services
KUBE_SERVICE_ADDRESSES="--service-cluster-ip-range=10.254.0.0/16"
# default admission control policies
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
# Add your own!
KUBE_API_ARGS="--client-ca-file=/srv/kubernetes/ca.crt --tls-cert-file=/srv/kubernetes/server.crt --tls-private-key-file=/srv/kubernetes/server.key --service_account_key_file=/srv/kubernetes/serviceaccount.key"
4)配置controller-manager
vi /etc/kubernetes/controller-manager
增加證書設置
# Add your own!
KUBE_CONTROLLER_MANAGER_ARGS="--root-ca-file=/srv/kubernetes/ca.crt --service_account_private_key_file=/srv/kubernetes/server.key"
5)啓動master上的服務
for SERVICES in etcd kube-apiserver kube-controller-manager kube-scheduler; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICES done
3.安裝kubernetes minion節點
yum install kubernetes -y
1)配置kubelet
vi /etc/kubernetes/config
將KUBE_MASTER的值修改爲正確的IP地址。
# logging to stderr means we get it in the systemd journal
KUBE_LOGTOSTDERR="--logtostderr=true"
# journal message level, 0 is debug
KUBE_LOG_LEVEL="--v=0"
# Should this cluster be allowed to run privileged docker containers
KUBE_ALLOW_PRIV="--allow-privileged=true"
# How the controller-manager, scheduler, and proxy find the apiserver
KUBE_MASTER="--master=http://master:8080"
vi /etc/kubernetes/kubelet
# The address for the info server to serve on (set to 0.0.0.0 or "" for all interfaces)
KUBELET_ADDRESS="--address=0.0.0.0"
# The port for the info server to serve on
# KUBELET_PORT="--port=10250"
# You may leave this blank to use the actual hostname
KUBELET_HOSTNAME="--hostname-override=${YOUR_HOST_NAME}"
# location of the api-server
KUBELET_API_SERVER="--api-servers=http://master:8080"
# pod infrastructure container
KUBELET_POD_INFRA_CONTAINER="--pod-infra-container- image=registry.access.redhat.com/rhel7/pod-infrastructure:latest"
# Add your own!
KUBELET_ARGS=""
2)配置kube-proxy
vi /etc/kuerbnetes/proxy,可以配置proxy模式
# Add your own!
KUBE_PROXY_ARGS=" --proxy-mode=iptables"
3)啓動minon上的服務
for SERVICES in kube-proxy kubelet docker; do
systemctl restart $SERVICES
systemctl enable $SERVICES
systemctl status $SERVICESdone
4.檢查kubernetes 集羣狀態
等服務啓動完成後,在master節點上檢查集羣狀況。測試環境上master上也部署了成了minion節點。
[root@master ~]# kubectl get nodes
NAME LABELS STATUS AGE
master kubernetes.io/hostname=master Ready 6d
minion1 kubernetes.io/hostname=minion1 Ready 6d
minion2 kubernetes.io/hostname=minion2 Ready 6d
安裝Calico
1.節點安裝calico (使用v0.18.0版本)
wget -o /usr/bin/calicoctl https://github.com/projectcalico/calico-containers/releases/download/v0.18.0/calicoctl
chmod +x /usr/bin/calicoctl
創建文件/etc/systemd/calico-node,設置etcd集羣服務地址:
[Unit]
Description=calicoctl node
After=docker.service
Requires=docker.service
[Service]
User=root
Environment=ETCD_AUTHORITY=master:4001
PermissionsStartOnly=true
ExecStart=/usr/bin/calicoctl node --detach=false
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
將calico-node配置成開機啓動服務,並啓動。
在環境變量中增加ETCD_AUTHORITY=master:4001的配置
systemctl enable /etc/systemd/calico-node.service
service calico-node restart
將會使用鏡像calico/node:v0.18.0,啓動服務。
2.在所有minion節點上,安裝calico-cni擴展
wget -N -P /opt/cni/bin https://github.com/projectcalico/calico-cni/releases/download/v1.1.0/calico chmod +x /opt/cni/bin/calico
wget -N -P /opt/cni/bin https://github.com/projectcalico/calico-cni/releases/download/v1.1.0/calico-ipam
chmod +x /opt/cni/bin/calico-ipam
配置cni網絡聲明:
$ cat /etc/cni/net.d/10-calico.conf
{
"name" : "calico-k8s-network",
"type" : "calico",
"etcd_authority" : "master:4001",
"log_level" : "info",
"ipam" : {
"type" : "calico-ipam"
}
}
如果是在阿里雲上部署,需要設置calico使用ipip,用如下命令查看:
calicoctl pool show --ipv4
如果顯示
+----------------+-------------------+
| IPv4 CIDR | Options |
+----------------+-------------------+
| 192.168.0.0/16 | ipip,nat-outgoing |
+----------------+-------------------+
表示已啓用ipip,否則根據提示刪除ip池,重新添加並使用選項–ipip –nat-outgoing。
查看默認規則是否正確:
calicoctl profile calico-k8s-network rule show
如果顯示
Inbound rules:
1 allow
Outbound rules:
1 allow
表示默認規則正確。
驗證網絡環境是否滿足kubernetes需求:
1) 創建一個rc,副本數量和集羣的minion節點一致。
2) 測試主機到pod通信:主機 ping 本機PodIp, 主機ping 其它主機PodIp。Pod內部ping宿主機Ip,Pod內部ping其它主機Ip。
3) 測試cluster ip通信:創建service,後端使用可用的Pod服務。在Pod所在minion,使用serviceIp+port訪問服務。在其它minion,使用serviceIp+port訪問服務。
4) 測試nodePort通信:使用minion本機IP+nodeport訪問服務。使用其它minion ip+nodeport訪問服務。
如果以上測試全部通過,則網絡配置正確,否則需要排查問題。
如果排查後配置全部正確,但是kubermetes網絡某些環節不通,可以在所有節點執行:
calicoctl node
命令,重新初始化calico網絡的鏈接。
3.部署policy-agent
使用下面的yaml文件部署policy-agent,其機制爲監聽kubernetes 中pod和namespace的變化,namespace中network policy的配置變化,有policy-agent寫入到calico的etcd存儲中,然後直接由每個節點上的felix轉換爲iptables規則。
apiVersion: v1
kind: Namespace
metadata:
name: calico-system
---
apiVersion: v1
kind: ReplicationController
metadata:
name: calico-policy-agent
namespace: calico-system
labels:
version: v0.1.2
projectcalico.org/app: "policy-agent"
spec:
replicas: 2
selector:
version: v0.1.2
projectcalico.org/app: "policy-agent"
template:
metadata:
labels:
version: v0.1.2
projectcalico.org/app: "policy-agent"
spec:
containers:
- name: policyagent
image: 172.16.10.5:5000/calico/k8s-policy-agent:v0.1.2
imagePullPolicy: IfNotPresent
env:
- name: ETCD_ENDPOINTS
value: "http://172.16.10.2:2379"
部署完成後,等待服務啓動。文件中的env是讓pod使用環境變量方式訪問ETCD,如果kubernetes集羣中安裝了DNS,可以刪掉環境變量的設置,使用dns訪問ETCD服務。
在master節點上,policy用於操作network policy對象實現網絡隔離的動態控制。
wget https://github.com/projectcalico/k8s-policy/releases/download/v0.1.1/policy
chmod +x ./policy
4.修改kubernetes配置
設置kube-proxy服務的proxy-mode配置爲iptables,修改配置文件/etc/kubernetes/proxy:
###
# kubernetes proxy config
# default config should be adequate
# Add your own!
KUBE_PROXY_ARGS=" --proxy-mode=iptables"
設置kubelet的network-plugin爲cni,修改配置文件/usr/lib/systemd/system/kubelet.service:
[Unit]
Description=Kubernetes Kubelet Server
Documentation=https://github.com/GoogleCloudPlatform/kubernetes
After=docker.service
Requires=docker.service
[Service]
WorkingDirectory=/var/lib/kubelet
EnvironmentFile=-/etc/kubernetes/config
EnvironmentFile=-/etc/kubernetes/kubelet
ExecStart=/usr/bin/kubelet \
--network-plugin-dir=/etc/cni/net.d \
--network-plugin=cni \
$KUBE_LOGTOSTDERR \
$KUBE_LOG_LEVEL \
$KUBELET_API_SERVER \
$KUBELET_ADDRESS \
$KUBELET_PORT \
$KUBELET_HOSTNAME \
$KUBE_ALLOW_PRIV \
$KUBELET_POD_INFRA_CONTAINER \
$KUBELET_ARGS
Restart=on-failure
[Install]
WantedBy=multi-user.target
重啓相關服務:
service kubelet restart
service kube-proxy restart
安裝nfs服務
1.安裝nfs相關服務
yum install nfs-server
yum install nfs
yum install rpcbind nfs-utils
2.添加共享目錄
/share *(rw,insecure,sync,no_subtree_check,no_root_squash)
/mysql *(rw,insecure,sync,no_subtree_check,no_root_squash)
上述共享目錄的配置一定要寫上,否則在使用過程中可能出現Operation not permitted錯誤。
3.所有kubernetes minion節點安裝nfs工具
yum install rpcbind nfs-utils
- 整體測試
常見問題及解決方案
1.kubernetes dns服務異常
首先查看kubelet是否配置正確,安裝dns需要在所有節點的kubelet啓動參數中增加
--cluster-dns=10.254.0.3 --cluster-domain=cluster.local
參數。
其次查看dns版本,確定kube2sky和kubernetes api通信的方式,老版本的(如v9版本),需要在yaml文件中指定kubernetes apiserver的地址和端口。新版本的(如v11版本),使用kubernetes默認的kubernetes service訪問kubernetes。如果是新版本,請參考 配置crt通信證書 一節,修改crt證書生成方式。 如果是老版本,確定kubernetes的網絡是否配置正確。
2.pv和pvc綁定失敗
pv和pvc匹配要檢查以下幾點:
1) pv和pvc的標籤是否一致。
2) pv和pvc的大小是否滿足要求,pvc的容量要求不能大於pv的容量。
3) pv和pvc的accessModes必須相同。
3.mysql容器使用nfs啓動不了
查看mysql對應Pod的日誌,如果出現Operation not permitted錯誤,是因爲nfs設置的共享目錄權限不足,在共享目錄設置中增加no_root_squash設置。
4.kubernetes https訪問權限問題
訪問Pod中服務可能會報以下錯誤:
x509: cannot validate certificate for x.x.x.x because it doesn't contain any IP SANs
這個是因爲沒有設置或者設置的證書出錯,參考 配置crt通信證書 重新生成證書,修改配置即可。
5.guestbook服務寫數據無響應
這個是因爲guestbook要使用的angular.min.js需要翻牆才能使用,可以把js文件下載到本地,重新生成鏡像。
6.cassandra服務無法訪問kubernetes api
v6版本的cassandra使用的SeedProvider有BUG,使用的默認的服務域名爲
kubernetes.default.cluster.local
正確的應該是
kubernetes.default.svc.cluster.local
這個只能通過重新編譯源碼,打包鏡像解決。
v7版本的鏡像因權限問題cassandra啓動腳本執行失敗。沒有深入研究解決方法。
v8版本已經解決了上述問題,但是沒有找到可以使用的鏡像。
7.nslookup解析正常,不能用域名訪問服務
查看主機的/etc/resolv.conf文件,如果存在類似記錄則刪除掉:
options timeout:1 attempts:1 rotate
8.問題排查方法
1) kubectl describe pod POD_NAME –namespace=NAME_SPACE查看Pod的事件及基本信息。如下載鏡像失敗等問題都可以從這塊定位出來。
2) kubectl logs POD_NAME –namespace=NAME_SPACE查看Pod的日誌,定位服務本身的問題,具體問題具體分析。
3) 在Pod內部訪問kubernetes apiserver有兩種方式。
一種是指定apiserver的地址和端口,如果使用這種方式訪問失敗,比如timeout,可以從集羣網絡環境入手排查問題。
另一種是使用kubernetes的默認service訪問,這種訪問方式使用的是https,並且依賴於集羣dns服務。如果出現問題,先排查集羣的dns服務是否安裝正確。創建busybox Pod,執行
kubectl exec busybox nslookup kubernetes.default.svc.cluster.local --namespace=kube-system
Server: 10.254.0.3
Address 1: 10.254.0.3
Name: kubernetes.default.svc.cluster.local
Address 1: 10.254.0.1
如果可以正確解析域名說明服務正常。
其次排查集羣crt證書是否配置正確。使用命令:
kubectl exec frontend-0ghx0 ls /var/run/secrets/kubernetes.io/serviceaccount/
查看Pod內部證書和crt文件。
9.kubernetes升級
centos源安裝的kubernetes有很多問題,可以使用官方release的版本升級kubernetes。升級方式是下載二進制包,停止kubernetes服務,用下載的二進制包替換老的二進制包,重新啓動服務即可。