K8s概念和单机应用

K8s概念和单机应用

evobot 1,108 2021-01-29

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的创建,启动,监控,重启,销毁,以及实现负载均衡。

k8s架构

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:

tomcat

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)


# k8s