kubernetes是一个开源系统,主要用来自动部署,扩容缩容和管理容器。在kubernetes中,service是核心,大多数时候我们并不需要关注kubernetes怎么工作的,只需要关心它提供了什么service。
k8s的概念
基础架构
在kubernetes中,提供service的是容器,为了保证service的高可用,提供service的容器不能只有一个,需要一组,这一组容器我们称之为pod。
为了实现service和pod之间的关联,又有了标签(label)的概念,我们把功能相同的pod设定为同一个标签。比如可以把所有提供MySQL服务的pod贴上标签name=mysql,这样MySQL service要作用于所有包含name=service标签的pod上。
pod运行在Node上,Node可以是一台物理机,也可以是虚拟机,通常一个Node上会运行几百个pod,每个pod里运行一个特殊的容器,叫做Pause,其他容器叫做业务容器,业务容器共享Pause容器的网络栈和Volume挂载卷,因此同一个pod内的业务容器之间的通信和数据交换更为高效。
在集群管理方面,k8s将集群中的机器划分为一个master节点和一群工作节点Node,其中master上运行着kuber-apiserver、kube-controller-manager、kube-scheduler,他们实现了资源管理,pod调度,弹性伸缩,安全控制,系统监控,纠错等功能。Node是工作节点,运行应用程序,提供服务。Node上的最小单元是pod,Node上运行着k8s的kubelet,kube-proxy服务进程,它们负责pod的创建,启动,监控,重启,销毁,以及实现负载均衡。
RC
扩容和升级需要一个关键的东西,Replication controller(RC),RC需要包含3个关键信息:
- 目标pod的定义
- 目标pod需要运行的副本数量(replicas)
- 要监控的目标pod的标签(Label)
RC的工作过程:首先在RC里定义好3个指标,k8s会根据RC定义的Label筛选出对应的pod,并实时监控其状态和数量,当实例数量少于定义的副本数(replicas),则会根据RC定义的pod模板来创建新的pod,然后将此pod调度到合适的Node上启动并运行,该过程完全自动化,不需要人工干预。
kubernetes单机应用
安装k8s
单机安装kubernetes,只需要使用yum安装即可:
# etcd是k8s的分布式存储,用来存储k8s的配置文件
yum install etcd kubernetes
修改docker配置文件/etc/sysconfig/docker
,将--selinux-enabled
改为--selinux-enabled=false --insecure-registry gcr.io
,其中--insecure-registry
配置是为了让docker允许使用http协议,默认docker是使用https协议:
OPTIONS='--selinux-enabled=false --insecure-registry gcr.io --log-driver=journald --signature-verification=false'
然后编辑/etc/kubernetes/apiserver
配置,删除--admission_control
参数中的ServiceAccount
:
# default admission control policies
KUBE_ADMISSION_CONTROL="--admission-control=NamespaceLifecycle,NamespaceExists,LimitRanger,SecurityContextDeny,ResourceQuota"
接着安装python-rhsm-certificates
软件包,如果安装时提示软件包已被取代,则需要下载rpm包安装:
wget http://mirror.centos.org/centos/7/os/x86_64/Packages/python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm
rpm2cpio python-rhsm-certificates-1.19.10-1.el7_4.x86_64.rpm | cpio -iv --to-stdout ./etc/rhsm/ca/redhat-uep.pem > /etc/rhsm/ca/redhat-uep.pem
完成后,为docker配置加速器,编辑/etc/docker/daemon.json
,添加以下内容:
{
"registry-mirrors": ["http://f1361db2.m.daocloud.io"]
}
保存之后,按顺序启动所有的服务:
for s in etcd docker kube-apiserver kube-controller-manager kube-scheduler kubelet kube-proxy;do systemctl start $s;done
创建RC文件
创建mysql-rc.yaml
文件,编辑内容如下:
apiVersion: v1
# 副本控制器RC
kind: ReplicationController
metadata:
# RC的名称,全局唯一
name: mysql
spec:
# pod副本的期待数量
replicas: 1
selector:
# 符合目标的Pod拥有此标签
app: mysql
# 根据下面的模板创建Pod的副本(实例)
template:
metadata:
# Pod副本拥有的标签,对应RC的selector
labels:
app: mysql
spec:
# Pod里容器的定义部分
containers:
# 容器的名称
- name: mysql
#容器对应的docker image
image: mysql:5.7
ports:
# 容器应用监听的端口号
- containerPort: 3306
# 注入容器内的环境变量
env:
- name: MYSQL_ROOT_PASSWORD
value: "123456"
保存rc文件之后,就可以使用配置文件来创建rc,执行命令kubectl create -f mysql-rc.yaml
:
[root@centos_1 k8s]# kubectl create -f mysql-rc.yaml
replicationcontroller "mysql" created
[root@centos_1 k8s]# tail -f /var/log/messages
Jan 28 22:04:31 centos_1 mysqld: Shutting down MySQL.. SUCCESS!
Jan 28 22:04:31 centos_1 systemd: Stopped LSB: start and stop MySQL.
Jan 28 22:04:39 centos_1 systemd: Reloading.
Jan 28 22:06:26 centos_1 kube-controller-manager: I0128 22:06:26.065929 3979 event.go:217] Event(api.ObjectReference{Kind:"ReplicationController", Namespace:"default", Name:"mysql", UID:"0279318b-6172-11eb-bea6-000c2984904c", APIVersion:"v1", ResourceVersion:"1779", FieldPath:""}): type: 'Normal' reason: 'SuccessfulCreate' Created pod: mysql-kl9sb
Jan 28 22:06:26 centos_1 kube-controller-manager: I0128 22:06:26.068791 3979 replication_controller.go:322] Observed updated replication controller mysql. Desired pod countchange: 1->1
Jan 28 22:06:26 centos_1 kube-scheduler: I0128 22:06:26.070763 3990 event.go:217] Event(api.ObjectReference{Kind:"Pod", Namespace:"default", Name:"mysql-kl9sb", UID:"0279d63f-6172-11eb-bea6-000c2984904c", APIVersion:"v1", ResourceVersion:"1780", FieldPath:""}): type: 'Normal' reason: 'Scheduled' Successfully assigned mysql-kl9sb to 127.0.0.1
Jan 28 22:06:26 centos_1 dockerd-current: time="2021-01-28T22:06:26.071526376+08:00" level=error msg="Handler for GET /v1.26/images/registry.access.redhat.com/rhel7/pod-infrastructure:latest/json returned error: No such image: registry.access.redhat.com/rhel7/pod-infrastructure:latest"
Jan 28 22:06:26 centos_1 kube-controller-manager: I0128 22:06:26.072621 3979 replication_controller.go:322] Observed updated replication controller mysql. Desired pod countchange: 1->1
Jan 28 22:06:26 centos_1 kubelet: E0128 22:06:26.562215 4586 docker_manager.go:2159] Failed to create pod infra container: ErrImagePull; Skipping pod "mysql-kl9sb_default(0279d63f-6172-11eb-bea6-000c2984904c)": image pull failed for registry.access.redhat.com/rhel7/pod-infrastructure:latest, this may be because there are no credentials on this request. details: (open /etc/docker/certs.d/registry.access.redhat.com/redhat-ca.crt: no such file or directory)
- 可以看到上面pull image报错,该报错就是因为没有手动安装
python-rhsm-certificates
软件包。
修复错误后,执行kubectl delete -f mysql-rc.yaml
删除rc,然后再次创建,查看日志:
Jan 29 22:06:52 centos_1 kube-controller-manager: I0129 22:06:52.369605 2726 replication_controller.go:322] Observed updated replication controller mysql. Desired pod count change: 1->1
Jan 29 22:06:53 centos_1 kube-scheduler: I0129 22:06:53.351611 2733 event.go:217] Event(api.ObjectReference{Kind:"Pod", Namespace:"default", Name:"mysql-btd2t", UID:"3c8dd63c-623b-11eb-a8e5-000c2984904c", APIVersion:"v1", ResourceVersion:"14010", FieldPath:""}): type: 'Warning' reason: 'FailedScheduling' no nodes available to schedule pods
Jan 29 22:06:55 centos_1 kube-scheduler: I0129 22:06:55.353869 2733 event.go:217] Event(api.ObjectReference{Kind:"Pod", Namespace:"default", Name:"mysql-btd2t", UID:"3c8dd63c-623b-11eb-a8e5-000c2984904c", APIVersion:"v1", ResourceVersion:"14010", FieldPath:""}): type: 'Warning' reason: 'FailedScheduling' no nodes available to schedule pods
Jan 29 22:06:59 centos_1 kube-scheduler: I0129 22:06:59.356064 2733 event.go:217] Event(api.ObjectReference{Kind:"Pod", Namespace:"default", Name:"mysql-btd2t", UID:"3c8dd63c-623b-11eb-a8e5-000c2984904c", APIVersion:"v1", ResourceVersion:"14010", FieldPath:""}): type: 'Warning' reason: 'FailedScheduling' no nodes available to schedule pods
Jan 29 22:07:00 centos_1 kube-controller-manager: I0129 22:07:00.008873 2726 garbagecollector.go:780] Garbage Collector: All monitored resources synced. Proceeding to collect garbage
Jan 29 22:07:05 centos_1 kube-controller-manager: I0129 22:07:05.052893 2726 nodecontroller.go:585] NodeController detected that some Nodes are Ready.Exiting master disruption mode.
创建成功后,使用下面的命令查看rc和pod的状态,状态为running则表示正常:
[root@centos_1 k8s]# kubectl get rc
NAME DESIRED CURRENT READY AGE
mysql 1 1 1 2m
[root@centos_1 k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-btd2t 1/1 Running 0 3m
使用kubectl get service
或者kubectl get svc
可以查看service的状态:
[root@centos_1 k8s]# kubectl get service
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 1d
创建service
可以看到目前service只有一个kubernetes自己的服务,我们还需要自己创建一个service,创建mysql-svc.yaml
文件,写入以下内容:
apiVersion: v1
kind: Service
metadata:
name: mysql
spec:
ports:
- port: 3306
selector:
app: mysql
- 其中kind定义service,metadata定义service的名称,port定义mysql的端口,selector定义service的lable
完成后执行kubectl create -f mysql-svc.yaml
创建service,然后使用kubectl get svc
查看服务状态:
[root@centos_1 k8s]# kubectl create -f mysql-svc.yaml
service "mysql" created
[root@centos_1 k8s]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 1d
mysql 10.254.123.190 <none> 3306/TCP 7s
然后我们就可以通过k8s显示的mysql的port 3306和ip访问mysql服务:
[root@centos_1 k8s]# mysql -uroot -p123456 -h10.254.123.190
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.6.50 MySQL Community Server (GPL)
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.
Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql>
创建web应用
mysql创建完成后,我们再创建一个tomcat的web应用,用来和上面的mysql服务通信
- 创建
myweb-rc.yaml
文件,写入以下内容:
kind: ReplicationController
metadata:
name: myweb
spec:
replicas: 1
selector:
app: myweb
template:
metadata:
labels:
app: myweb
spec:
containers:
- name: myweb
image: kubeguide/tomcat-app:v1
ports:
- containerPort: 8080
env:
- name: MYSQL_SERVICE_HOST
# 这里填入k8s分给mysql的ip地址,如果搭建了k8s的DNS服务,这里可以直接写mysql的service name
value: '10.254.123.190'
- name: MYSQL_SERVICE_PORT
value: '3306'
- 保存后执行
kubectl create -f myweb-rc.yaml
创建tomcat的rc:
[root@centos_1 k8s]# kubectl create -f myweb-rc.yaml
replicationcontroller "myweb" created
# 状态是正常创建容器
[root@centos_1 k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-btd2t 1/1 Running 0 31m
myweb-r94z9 0/1 ContainerCreating 0 13s
# rc正常运行
[root@centos_1 k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-btd2t 1/1 Running 0 33m
myweb-r94z9 1/1 Running 0 1m
- 接着创建
myweb-svc.yaml
文件,内容如下:
kind: Service
metadata:
name: myweb
spec:
type: NodePort
ports:
- port: 8080
nodePort: 30001
selector:
app: myweb
上面的svc定义多了一个nodeport,nodeport是用来将node的端口与service的端口做映射,让我们能够通过node的ip和端口访问到定义的服务,在k8s中,nodeport必须定义30000以上的端口号
- 创建service:
[root@centos_1 k8s]# kubectl get pod
NAME READY STATUS RESTARTS AGE
mysql-btd2t 1/1 Running 0 50m
myweb-r94z9 1/1 Running 0 18m
[root@centos_1 k8s]# kubectl create -f myweb-svc.yaml
service "myweb" created
[root@centos_1 k8s]# kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes 10.254.0.1 <none> 443/TCP 1d
mysql 10.254.123.190 <none> 3306/TCP 32m
myweb 10.254.224.60 <nodes> 8080:30001/TCP 3s
创建成功后,可以使用curl 10.254.224.60:8080/demo/
访问tomcat服务,也可以浏览器访问node的ip:30001/demo/访问,正确页面如下,同时也说明tomcat也连接到了mysql:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| HPE_APP |
| mysql |
| performance_schema |
+--------------------+
4 rows in set (0.00 sec)
mysql> use HPE_APP;
Database changed
mysql> show tables;
+-------------------+
| Tables_in_HPE_APP |
+-------------------+
| T_USERS |
+-------------------+
1 row in set (0.00 sec)