初阶k8s集群搭建
时隔大半年,我又回来了,这回带来的是最近非常火的容器编排工具——kubernetes
先附上docker 官网和kubernetes中文社区链接,我搭建k8s的苦逼之路也是从这里开始的,想了解docker 和kubernetes是什么的朋友或者是初学者可以先看看
在去年年底公司领导提出的IT信息化变革, 紧跟新一代信息技术发展趋势,利用信息技术提高业务生产效率。所以我们尝试采用kubernetes、PaaS、DevOps作为支撑,来实现全新的IT信息化建设。
那在这个系列,就是把我整个搭建kubernetes过程以及过程中遇到的坑和教训以及解决方法等记录下来,方便自己和大家以后遇到相似的问题能得以解决,在接下来的文章里,为了书写方便,kubernetes我就用k8s来替代了。
我在一开始急于求成,想看看完整的一个k8s平台,于是采用了GitHub上面的一个开源脚本部署项目——kubekit 快速离线部署工具。
这个工具采用脚本的方式,通过脚本控制kubeadm以及可视化界面来完成master和node的部署,极大降低了k8s的入学门槛,方便一票的初学者窥探k8s世界,我就是其中一个。。哈哈
部署页面感兴趣的童鞋可以直接去GitHub上学习,上面有详细的安装教程,最高支持k8s1.9的版本,简单易用。
在玩腻了kubekit自动部署以后,我们我们想直接自己使用kubeadm来部署我们的k8s,想自己手动部署k8s一个很大的原因是因为使用kubekit控制台无法设置认证和授权,也不知道是什么原因,修改了apiserver配置文件以后就怎么也起不来了。因此,下面我详细解释一下我们使用kubeadm来离线部署k8s集群过程。
我们的k8s版本是目前比较新的1.10,首先准备三台linux ,机子硬件要就最好4核8G硬盘30G以上,vm或者别的虚拟机的话酌情降低,系统我用的是公司特意升级过的的redhat 7.2,centos7以上的机子也是可以的,并且已经安装好了docker ,这里我们使用的是docker-ce-17.03.0 CE版本,附上下载地址可能需要翻墙。。。
当然你也可以直接动过yum安装
安装完成后执行
systemctl start docker && systemctl enable docker
通过docker version 可以查看docker的版本
Client: Version: 17.03.2-ce API version: 1.27 Go version: go1.7.5 Git commit: f5ec1e2 Built: Tue Jun 27 02:21:36 2017 OS/Arch: linux/amd64Server: Version: 17.03.2-ce API version: 1.27 (minimum version 1.12) Go version: go1.7.5 Git commit: f5ec1e2 Built: Tue Jun 27 02:21:36 2017 OS/Arch: linux/amd64 Experimental: false
安装k8s之前三台机子的环境得配好
每一台机子执行以下命令
systemctl stop firewalld && systemctl disable firewalld
setenforce 0
echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables
echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
echo 1 > /proc/sys/net/ipv4/ip_forward
sysctl -w net.bridge.bridge-nf-call-iptables=1
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
net.bridge.bridge-nf-call-iptables=1
net.bridge.bridge-nf-call-ip6tables=1
sysctl -p
swapoff -a
有人可能疑惑,为什么要关掉swap,那是跟k8s的设计初衷有关,k8s的想法是将实例紧密包装到尽可能接近100%。 所有的部署应该与CPU /内存限制固定在一起。 所以如果调度程序发送一个pod到一台机器,它不应该使用交换。 设计者不想交换,因为它会减慢速度。
所以关闭swap主要是为了性能考虑。当然为了一些节省资源的场景,比如运行容器数量较多,可添加kubelet参数 --fail-swap-on=false来解决。
摘抄自https://blog.csdn.net/liuliuzi_hz/article/details/79076553
安装k8s需要以下安装包
socat-1.7.3.2-2.el7.x86_64.rpm、kubernetes-cni-0.6.0-0.x86_64.rpm、kubeadm-1.10.0-0.x86_64.rpm、kubectl-1.10.0-0.x86_64.rpm、kubelet-1.10.0-0.x86_64.rpm、kubernetes-cni-0.6.0-0.x86_64.rpm
到安装包目录下执行yum install -y *.rpm 来完成k8s组件的安装。
因为是离线安装,k8s需要的相关镜像我们也得准备好
Master
docker load < k8s_images/docker_images/etcd-amd64_v3.1.10.tar
docker load < k8s_images/docker_images/flannel\:v0.9.1-amd64.tar
docker load < k8s_images/docker_images/k8s-dns-dnsmasq-nanny-amd64_v1.14.7.tar
docker load < k8s_images/docker_images/k8s-dns-kube-dns-amd64_1.14.7.tar
docker load < k8s_images/docker_images/k8s-dns-sidecar-amd64_1.14.7.tar
docker load < k8s_images/docker_images/kube-apiserver-amd64_v1.9.0.tar
docker load < k8s_images/docker_images/kube-controller-manager-amd64_v1.9.0.tar
docker load < k8s_images/docker_images/kube-scheduler-amd64_v1.9.0.tar
docker load < k8s_images/docker_images/kube-proxy-amd64_v1.9.0.tar
docker load < k8s_images/docker_images/pause-amd64_3.0.tar
docker load < k8s_images/kubernetes-dashboard_v1.8.1.tar
nodes
docker load < k8s_images/docker_images/kube-proxy-amd64_v1.9.0.tar
docker load < k8s_images/docker_images/pause-amd64_3.0.tar
docker load < k8s_images/kubernetes-dashboard_v1.8.1.tar
docker load < flannel.tar
因为导入进去的镜像镜像名和kubeadm需要安装的镜像名不同,因此需要修改相应的镜像名,例:docker tag IMAGESname:xxx quay.io/coreos/flannel:v0.9.1
这里也可以通过脚本的方式去一键改名:
vim auto_changeName.sh
images=(gcr.io/google_containers
k8s-dns-kube-dns-amd64:1.14.9
k8s-dns-sidecar-amd64:1.14.9
k8s-dns-dnsmasq-nanny-amd64:1.14.9
kube-proxy-amd64:v1.10.0
kube-apiserver-amd64:v1.10.0
kube-controller-manager-amd64:v1.10.0
kube-scheduler-amd64:v1.10.0
etcd-amd64:3.1.12
kubernetes-dashboard-amd64:v1.8.3
pause-amd64:3.1
)
for imageName in ${images[@]} ;
do
docker tag gcr.io/google_containers/$imageName k8s.gcr.io/$imageName
docker rmi -f gcr.io/google_containers/$imageName
done
然后赋予脚本执行权限chmod +x *.sh
执行./*.sh
注意在执行kubeadm init 之前,务必检查docker 的Cgroup Driver,如果是cgroupfs的话,则每一台节点都执行
sed -i -e 's/cgroup-driver=systemd/cgroup-driver=cgroupfs/g' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
systemctl daemon-reload && systemctl restart kubelet
kubeadm reset
Master
在Master上执行kubeadm init --kubernetes-version=v1.10.0 --pod-network-cidr=10.244.0.0/16
kubernetes默认支持多重网络插件如flannel、weave、calico,这里使用flanne,就必须要设置--pod-network-cidr参数,10.244.0.0/16是kube-flannel.yml里面配置的默认网段,如果需要修改的话,需要把kubeadm init的--pod-network-cidr参数和后面的kube-flannel.yml里面修改成一样的网段就可以了。——https://segmentfault.com/a/1190000012755243
如果kubeadm init安装失败,可以通过kubeadm reset 重置,通过journalctl -xeu kubelet 查看服务启动日志。
安装成功应该会有kubeadm join ip:6443 --token n95wls.h1ifw0ln1mzlmfhu --discovery-token-ca-cert-hash sha256:XXX。
记得保存以上信息,因为node节点加入需要使用。
如果忘记了,可以在master上通过kubeadmin token list得到
默认token 24小时就会过期,后续的机器要加入集群需要重新生成token。使用命令kubeadm token create
按照上面提示,此时root用户还不能使用kubelet控制集群需要,配置下环境变量
对于非root用户
mkdir -p$HOME/.kube
cp -i/etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g)$HOME/.kube/config
对于root用户
export KUBECONFIG=/etc/kubernetes/admin.conf
也可以直接放到~/.bash_profile
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
source一下环境变量
source ~/.bash_profile
然后执行kubectl get nodes 查看节点状态,不出意外的话应该是NoReady,那是因为没有网络组件。我们使用fannel
下载此文件
wget https://raw.githubusercontent.com/coreos/flannel/v0.9.1/Documentation/kube-flannel.yml
若要使用的是自己的私服镜像,或者修改网段,需要kubeadm --pod-network-cidr=和这里同步
vim kube-flannel.yml
修改imges、network项
执行
kubectl create -f kube-flannel.yml
通过kubectl get pods --all-namespaces 查看flannelpod状态
如果没有问题的话再次执行kubectl get nodes 会发现master节点已经变成Ready。
如果部署flannel出现问题,可以通过
kubectl describe pod flannel -n namespaces //查看部署日志
修改kube-flannel.yml后可以通过kubectl apply -f kube-flannel.yml来更新
多半是因为网络地址没写对或者镜像地址错误导致的。
node
使用刚刚kubeadm后的kubeadm join --xxx
如果失败,可能是因为忘记修改cgroup,一定要学会查看错误日志
sed -i -e 's/cgroup-driver=systemd/cgroup-driver=cgroupfs/g' /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
systemctl daemon-reload && systemctl restart kubelet
kubeadm reset
然后重新join一次,不出意外地话应该会出现success。
通过kubectl get nodes 查看master和node状态。kubernetes基本集群安装完成。如果需要添加新的节点亦是如此。
部署kubernetes-dashboard
虽然这个组件在我参考的文章中说的很不好用,功能太少,但是在我看来还是非常好用的,对于初学者 配合heapster查看pod和各种deployment以及节点状态还是非常方便的,更新和删除以及查看日志都很方便
kubernetes-dashboard部署kubernetes-dashboard.yaml
apiVersion: v1
kind: Secret
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard-certs
namespace: kube-system
type: Opaque
---
# ------------------- Dashboard Service Account ------------------- #
apiVersion: v1
kind: ServiceAccount
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
---
# ------------------- Dashboard Role & Role Binding ------------------- #
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
rules:
# Allow Dashboard to create 'kubernetes-dashboard-key-holder' secret.
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
# Allow Dashboard to create 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["create"]
# Allow Dashboard to get, update and delete Dashboard exclusive secrets.
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["kubernetes-dashboard-key-holder", "kubernetes-dashboard-certs"]
verbs: ["get", "update", "delete"]
# Allow Dashboard to get and update 'kubernetes-dashboard-settings' config map.
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["kubernetes-dashboard-settings"]
verbs: ["get", "update"]
# Allow Dashboard to get metrics from heapster.
- apiGroups: [""]
resources: ["services"]
resourceNames: ["heapster"]
verbs: ["proxy"]
- apiGroups: [""]
resources: ["services/proxy"]
resourceNames: ["heapster", "http:heapster:", "https:heapster:"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: kubernetes-dashboard-minimal
namespace: kube-system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: kubernetes-dashboard-minimal
subjects:
- kind: ServiceAccount
name: kubernetes-dashboard
namespace: kube-system
---
# ------------------- Dashboard Deployment ------------------- #
kind: Deployment
apiVersion: apps/v1beta2
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
k8s-app: kubernetes-dashboard
template:
metadata:
labels:
k8s-app: kubernetes-dashboard
spec:
containers:
- name: kubernetes-dashboard
image: 192.168.220.84/kubernetes/kubernetes-dashboard-amd64:v1.8.3
ports:
- containerPort: 8443
protocol: TCP
args:
- --auto-generate-certificates
- --authentication-mode=basic
# Uncomment the following line to manually specify Kubernetes API server Host
# If not specified, Dashboard will attempt to auto discover the API server and connect
# to it. Uncomment only if the default does not work.
# - --apiserver-host=http://my-address:port
volumeMounts:
- name: kubernetes-dashboard-certs
mountPath: /certs
# Create on-disk volume to store exec logs
- mountPath: /tmp
name: tmp-volume
livenessProbe:
httpGet:
scheme: HTTPS
path: /
port: 8443
initialDelaySeconds: 30
timeoutSeconds: 30
volumes:
- name: kubernetes-dashboard-certs
secret:
secretName: kubernetes-dashboard-certs
- name: tmp-volume
emptyDir: {}
serviceAccountName: kubernetes-dashboard
# Comment the following tolerations if Dashboard must not be deployed on master
tolerations:
- key: node-role.kubernetes.io/master
effect: NoSchedule
---
# ------------------- Dashboard Service ------------------- #
kind: Service
apiVersion: v1
metadata:
labels:
k8s-app: kubernetes-dashboard
name: kubernetes-dashboard
namespace: kube-system
spec:
type: NodePort
#type: ExternalName
#externalName: static.otherdomain.com
ports:
- port: 443
targetPort: 8443
nodePort: 31234
selector:
k8s-app: kubernetes-dashboard
nodeport端口范围30000-32767
31234就是我的映射端口,根docker run -d xxx:xxx差不多
部署kubernetes-dashboard
kubectl apply -f kubernetes-dashboard.yaml
部署kubernetes-dashboard插件heapster.yaml
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: heapster
namespace: kube-system
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: heapster
subjects:
- kind: ServiceAccount
name: heapster
namespace: kube-system
roleRef:
kind: ClusterRole
name: system:heapster
apiGroup: rbac.authorization.k8s.io
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: heapster
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
task: monitoring
k8s-app: heapster
spec:
serviceAccountName: heapster
containers:
- name: heapster
image: 192.168.220.84/third_party/heapster-amd64:v1.3.0
imagePullPolicy: IfNotPresent
command:
- /heapster
- --source=kubernetes:https://kubernetes.default
- --sink=influxdb:http://monitoring-influxdb.kube-system.svc:8086
---
apiVersion: v1
kind: Service
metadata:
labels:
task: monitoring
# For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons)
# If you are NOT using this as an addon, you should comment out this line.
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: Heapster
name: heapster
namespace: kube-system
spec:
ports:
- port: 80
targetPort: 8082
selector:
k8s-app: heapster
kubectl apply -f heapster.yaml
部署heapster数据库influxdb.yaml
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: monitoring-influxdb
namespace: kube-system
spec:
replicas: 1
template:
metadata:
labels:
task: monitoring
k8s-app: influxdb
spec:
containers:
- name: influxdb
image: 192.168.220.84/third_party/heapster-influxdb-amd64:v1.1.1
volumeMounts:
- mountPath: /data
name: influxdb-storage
volumes:
- name: influxdb-storage
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
task: monitoring
# For use as a Cluster add-on (https://github.com/kubernetes/kubernetes/tree/master/cluster/addons)
# If you are NOT using this as an addon, you should comment out this line.
kubernetes.io/cluster-service: 'true'
kubernetes.io/name: monitoring-influxdb
name: monitoring-influxdb
namespace: kube-system
spec:
ports:
- port: 8086
targetPort: 8086
selector:
k8s-app: influxdb
kubectl apply -f influxdb.yaml
当然里面所用到的镜像全部是我自己搭建的私服镜像仓库,大家可以自己按需求搭建,教程就不给了,参考https://blog.csdn.net/u012979009/article/details/70860107。
镜像和安装包在最后会附上下载地址。。。
如果heapster监控图标没有出来,可以尝试删除kubernetes-dashboard pod,然后等它自动重新部署,若还是无法展示,也可以通过kubectl logs podname的形式来查看日志。
认证和授权
部署了k8s的控制面板,并不是谁都可以访问谁都可以操作的,k8s的控制面板默认验证方式有kubeconfig和token,但是都比较难懂
这里我们使用basicauth的方式进行apiserver的验证
vim /etc/kubernetes/manifests/pki/basic-auth-file 用于存放用户名和密码
格式是密码,用户名,用户id
类似下面的例子
admin123,test,1
12345,admin,2
然后给kube-apiserver添加basic_auth验证
vim /etc/kubernetes/manifests/kube-apiserver.yaml
- command:
- --basic-auth-file=/etc/kubernetes/pki/basic-auth-file
保存。
注意,保存后apiserver会重新启动,不知道是bug还是什么我的机器在保存第一次的时候会存在apiserver无法启动的问题,必须再打开kube-apiserver.yaml一次再执行一次保存才能重启apiserver。
由于使用的是1.10版本,k8s1.6后版本都采用RBAC授权模型,我们还得给用户一些权限
在k8s里有一个宇宙无敌大的权限clusterrole cluster-admin,我们把这个权限附给我们的管理员用户
kubectl create clusterrolebinding login-on-dashboard-with-cluster-admin --clusterrole=cluster-admin --user=test
同时,如果你不想让用户没有那么大的权限,也可以自定义。对于授权认证方面我会在别的文章里再详细说。
设置完成后通过火狐浏览器(其他浏览器不一定行)访问https://ip:31234即可看到页面
登录页面输入用户名密码即可看到控制面板
这样简单的kubernetes集群就搭建完成了。
完全参考了kubernetes1.9离线部署,并做了自己实践的一些补充
密码:mdn6