centOS下单点部署k8s
Kubernetes 是Google的一种基于容器的开源服务编排解决方案,在我们进行Kubernetes的学习前,为了对Kubernetes的工作有一个大概的认识, 我们需要先安装一个单节点的实例服务,用于平常的开发与测试。在官网 中,有各种各样的搭建方式,但这里我们想要有更贴近实际的例子,只有这样才能让docker和k8s体现出关系的紧密。
我们先看k8s的架构图,以便对它的部署有个直观的了解
环境准备
本文的例子是基于Centos 7的Linux版本,大家也可以使用ubuntu或其他发行版,软件搭建的方式基本是差不多的,为了让例子更简单, 本文省去了网络Fannel的安装与配置,只做基本通用的开发环境搭建,希望对大家有帮助。
本例子用于测试的服务器ip为:172.16.21.35
yum源
为了让国内下载etcd和kubernetes更流畅,我们先切换阿里云的yum源
关闭防火墙服务
centos7 默认使用firewall为防火墙,而Kubernetes的Master与工作Node之间会有大量的网络通信,安全的做法是在防火墙上配置各种需要相互通讯的端口号,在一个安全的内部网络环境中可以关闭防火墙服务;
这里我们将其更改为iptables,具体步骤如下:
$ systemctl disable firewalld.service $ systemctl stop firewalld.service
安装iptables,其操作为:
$ yum install -y iptables-services $ systemctl start iptables.service $ systemctl enable iptables.service
安全设置 setenforce 0 查看iptables systemctl status iptables.service systemctl stop iptables.service 设置主机名 hostnamectl –static set-hostname centos-master 关闭Selinux /etc/selinux/config SELINUX=disabled
安装etcd和Kubernetes软件(docker会在安装kubernetes的过程中被安装)
$ yum install -y etcd kubernetes
配置修改
安装完服务组件后,我们需要修改相关的配置
Docker配置文件 /etc/sysconfig/docker,其中的OPTIONS的内容设置为:
$ vim /etc/sysconfig/docker OPTIONS='--selinux-enabled=false --insecure-registry gcr.io'
Kubernetes修改apiserver的配置文件,在/etc/kubernetes/apiserver中
$ vim /etc/kubernetes/apiserver KUBE_ADMISSION_CONTROL="--admission_control=NamespaceLifecycle,NamespaceExists, LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota"
去掉 ServiceAccount
选项。否则会在往后的pod创建中,会出现类似以下的错误:
Error from server: error when creating "mysql-rc.yaml": Pod "mysql" is forbidden:
no API token found for service account default/default,
retry after the token is automatically created and added to the service account
切换docker hub 镜像源
在国内为了稳定pull镜像,我们最好使用Daocloud的镜像服务 :)
curl -sSL https://get.daocloud.io/daotools/set_mirror.sh | sh -s http://dbe35452.m.daocloud.io
按顺序启动所有服务
systemctl start etcd systemctl start docker systemctl start kube-apiserver.service systemctl start kube-controller-manager.service systemctl start kube-scheduler.service systemctl start kubelet.service systemctl start kube-proxy.service
然后,我们检验下kubernetes的服务是否跑起来
ps -ef | grep kube
到目前为止,一个单机版的Kubernetes的环境就安装启动完成了。接下来,我就基于这个单机版,撸起袖子,认真干!!!
启动MySQL容器服务
我们先拉取mysql的服务镜像 :
sudo docker pull mysql 或 docker pull hub.c.163.com/library/mysql:latest
启动MySQL服务
首先为MySQL服务创建一个RC定义文件:mysql-rc.yaml,下面给出了该文件的完整内容
cat >mysql-rc.yaml<<-EOF apiVersion: v1 kind: ReplicationController metadata: name: mysql spec: replicas: 1 selector: app: mysql template: metadata: labels: app: mysql spec: containers: - name: mysql image: hub.c.163.com/library/mysql ports: - containerPort: 3306 env: - name: MYSQL_ROOT_PASSWORD value: "123456" EOF
yaml定义文件说明:
- kind:表明此资源对象的类型,例如上面表示的是一个RC
- spec: 对RC的相关属性定义,比如说spec.selector是RC的Pod标签(Label)选择器,既监控和管理拥有这些表情的Pod实例,确保当前集群上始终有且 仅有replicas个Pod实例在运行。
- spec.template定义pod的模板,这些模板会在当集群中的pod数量小于replicas时,被作为依据去创建新的Pod
创建好 mysql-rc.yaml后, 为了将它发布到Kubernetes中,我们在Master节点执行命令
$ kubectl create -f mysql-rc.yaml replicationcontroller "mysql” created
接下来,我们用kuberctl命令查看刚刚创建的RC:
$ kubectl get rc NAME DESIRED CURRENT READY AGE mysql 1 1 0 14s
查看Pod的创建情况,可以运行下面的命令:
$ kubectl get pods NAME READY STATUS RESTARTS AGE mysql-b0gk0 0/1 ContainerCreating 0 3s
可见pod的状态处于ContainerCreating,我们需要耐心等待一下,直到状态为Running
NAME READY STATUS RESTARTS AGE mysql-b0gk0 1/1 Running 0 6m
最后,我们创建一个与之关联的Kubernetes Service - MySQL的定义文件:mysql-svc.yaml
cat >mysql-svc.yaml<<-EOF apiVersion: v1 kind: Service metadata: name: mysql spec: ports: - port: 3306 selector: app: mysql EOF
其中 metadata.name是Service的服务名,port定义服务的端口,spec.selector确定了哪些Pod的副本对应本地的服务。
运行kuberctl命令,创建service:
$ kubectl create -f mysql-svc.yaml service "mysql" created
然后我们查看service的状态
$ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.254.0.1 <none> 443/TCP 18m mysql 10.254.185.20 <none> 3306/TCP 14s
注意到MySQL服务被分配了一个值为 10.254.185.20
的CLUSTER-IP,这是一个虚地址,随后,Kubernetes集群中的其他新创建的Pod就可以通过Service 的CLUSTER-IP+端口6379来连接和访问它了。
启动Web容器服务
先拉取一个测试镜像到本地
docker pull kubeguide/tomcat-app:v1
上面我们定义和启动了MySQL的服务,接下来我们用同样的步骤,完成Tomcat应用的服务启动过程,首先我们创建对应的RC文件 myweb-rc.yaml,具体内容如下:
cat >myweb-rc.yaml<<-EOF apiVersion: v1 kind: ReplicationController metadata: name: myweb spec: replicas: 5 selector: app: myweb template: metadata: labels: app: myweb spec: containers: - name: myweb image: docker.io/kubeguide/tomcat-app:v1 ports: - containerPort: 8080 env: - name: MYSQL_SERVICE_HOST value: "mysql" - name: MYSQL_SERVICE_PORT value: "3306" EOF
与mysql一样,我们创建rc服务:
$ kubectl create -f myweb-rc.yaml replicationcontroller "myweb" created $ kubectl get rc NAME DESIRED CURRENT READY AGE mysql 1 1 0 14m myweb 5 5 0 10s
接着,我们看下pods的状态:
$ kubectl get pods NAME READY STATUS RESTARTS AGE mysql-b0gk0 1/1 Running 0 15m myweb-1oyb7 1/1 Running 0 43s myweb-8ffs6 1/1 Running 0 43s myweb-xge1t 1/1 Running 0 43s myweb-xr214 1/1 Running 0 43s myweb-zia37 1/1 Running 0 43s
wow..从命理结果我们发现,我们yaml中声明的5个副本都被创建并运行起来了,我们隐约感受到k8s的威力咯
我们创建对应的Service, 相关的myweb-svc文件如下:
cat >myweb-svc<<-EOF apiVersion: v1 kind: Service metadata: name: myweb spec: type: NodePort ports: - port: 8080 nodePort: 30001 selector: app: myweb EOF
运行kubectl create 命令进行创建
$ kubectl create -f myweb-svc.yaml service "myweb" created
最后,我们使用kubectl查看前面创建的Service
[root@kdev tmp]# kubectl get services NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.254.0.1 <none> 443/TCP 4h mysql 10.254.185.20 <none> 3306/TCP 4m myweb 10.254.18.53 <nodes> 8080/TCP 57s
验证
通过上面的几个步骤,我们可以成功实现了一个简单的K8s单机版例子,我们可以在浏览器输入 http://172.16.21.35:30001/demo/ 来测试我们发布的web应用。
$ curl http://172.16.21.31:30001
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> ... ... ...
接下来就是安装kubernetes-dashboard ,下载kubernetes-dashboard.yaml文件,修改一下即可;
cat >kubernetes-dashboard.yaml<<-EOF kind: Deployment apiVersion: extensions/v1beta1 metadata: labels: app: kubernetes-dashboard name: kubernetes-dashboard namespace: kube-system spec: replicas: 1 selector: matchLabels: app: kubernetes-dashboard template: metadata: labels: app: kubernetes-dashboard # Comment the following annotation if Dashboard must not be deployed on master annotations: scheduler.alpha.kubernetes.io/tolerations: | [ { "key": "dedicated", "operator": "Equal", "value": "master", "effect": "NoSchedule" } ] spec: containers: - name: kubernetes-dashboard image: docker.io/mritd/kubernetes-dashboard-amd64 #默认的镜像是使用google的,这里改成内网 imagePullPolicy: Always ports: - containerPort: 9090 protocol: TCP args: # 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://172.16.21.35:8080 #注意这里是api的地址 livenessProbe: httpGet: path: / port: 9090 initialDelaySeconds: 30 timeoutSeconds: 30 --- kind: Service apiVersion: v1 metadata: labels: app: kubernetes-dashboard name: kubernetes-dashboard namespace: kube-system spec: type: NodePort ports: - port: 80 targetPort: 9090 selector: app: kubernetes-dashboard EOF
# kubectl create -f kubernetes-dashboard.yaml # kubectl get pods --all-namespaces NAMESPACE NAME READY STATUS RESTARTS AGE default nginx-controller-6n19x 1/1 Running 0 9m kube-system kubernetes-dashboard-2079301569-0qzdv 1/1 Running 0 12m