初阶k8s集群搭建

1字数 3946阅读 8105

时隔大半年,我又回来了,这回带来的是最近非常火的容器编排工具——kubernetes

先附上docker 官网和kubernetes中文社区链接,我搭建k8s的苦逼之路也是从这里开始的,想了解docker 和kubernetes是什么的朋友或者是初学者可以先看看

docker官网

k8s_Kubernetes中文社区

在去年年底公司领导提出的IT信息化变革, 紧跟新一代信息技术发展趋势,利用信息技术提高业务生产效率。所以我们尝试采用kubernetes、PaaS、DevOps作为支撑,来实现全新的IT信息化建设。

那在这个系列,就是把我整个搭建kubernetes过程以及过程中遇到的坑和教训以及解决方法等记录下来,方便自己和大家以后遇到相似的问题能得以解决,在接下来的文章里,为了书写方便,kubernetes我就用k8s来替代了。


我在一开始急于求成,想看看完整的一个k8s平台,于是采用了GitHub上面的一个开源脚本部署项目——kubekit 快速离线部署工具。

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版本,附上下载地址可能需要翻墙。。。

dockerRPM包下载地址

当然你也可以直接动过yum安装

dockerYUM安装方法

安装完成后执行

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

推荐阅读更多精彩内容