kubernetes入门案例

news/2024/11/29 18:49:23/

kubernetes入门案例

本文我们通过一个 Java Web 应用例子来介绍 kubernetes 的使用,可以让新手快速上手和实践。

此 Java Web 应用的结构比较简单,是一个运行在 Tomcat 里的 Web App,JSP 页面通过 JDBC 直接访问 MySQL

数据库并展示数据。出于演示和简化的目的,只要程序正确连接到了数据库,就会自动完成对应的 Table 的创建与

初始化数据的准备工作。所以,当我们通过浏览器访问此应用时,就会显示一个表格的页面,数据则来自数据库。

在这里插入图片描述

此应用需要启动两个容器:Web App 容器和 MySQL 容器,并且 Web App 容器需要访问 MySQL 容器。在

Docker 时代,假设我们在一个宿主机上启动了这两个容器,就需要把 MySQL 容器的 IP 地址通过环境变量注入

Web App 容器里;同时,需要将 Web App 容器的 8080 端口映射到宿主机的 8080 端口,以便在外部访问。在本

文的这个例子里,我们介绍在 Kubernetes 时代是如何达到这个目标的。

1、环境准备

首先需要安装 kubernetes 集群,这里我们将不在介绍安装,安装请参考其它文章,本文的环境:

[root@master ~]# kubectl get nodes
NAME      STATUS   ROLES                  AGE     VERSION
master    Ready    control-plane,master   6m5s    v1.21.0
master2   Ready    control-plane,master   4m57s   v1.21.0
slave1    Ready    <none>                 5m30s   v1.21.0
slave2    Ready    <none>                 5m28s   v1.21.0
[root@master ~]# kubectl get pods --all-namespaces
NAMESPACE     NAME                                      READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-b86879b9b-mb6hk   1/1     Running   0          24s
kube-system   calico-node-6v5kp                         1/1     Running   0          24s
kube-system   calico-node-c8l7v                         1/1     Running   0          24s
kube-system   calico-node-grlqh                         1/1     Running   0          24s
kube-system   calico-node-mr8rk                         1/1     Running   0          24s
kube-system   coredns-545d6fc579-42cxc                  1/1     Running   0          5m33s
kube-system   coredns-545d6fc579-lzgbz                  1/1     Running   0          5m33s
kube-system   etcd-master                               1/1     Running   0          5m49s
kube-system   etcd-master2                              1/1     Running   0          4m45s
kube-system   kube-apiserver-master                     1/1     Running   0          5m49s
kube-system   kube-apiserver-master2                    1/1     Running   0          4m49s
kube-system   kube-controller-manager-master            1/1     Running   1          5m49s
kube-system   kube-controller-manager-master2           1/1     Running   0          4m49s
kube-system   kube-proxy-8gj54                          1/1     Running   0          5m22s
kube-system   kube-proxy-9vc8c                          1/1     Running   0          4m49s
kube-system   kube-proxy-lpfnx                          1/1     Running   0          5m33s
kube-system   kube-proxy-mvphs                          1/1     Running   0          5m20s
kube-system   kube-scheduler-master                     1/1     Running   1          5m49s
kube-system   kube-scheduler-master2                    1/1     Running   0          4m49s

本文使用的 Docker 镜像地址: https://hub.docker.com/u/kubeguide/

2、启动MySQL服务

为 MySQL 服务创建一个 RC 定义文件 mysql-rc.yaml

apiVersion: v1
# 副本控制器RC
kind: ReplicationController
metadata:# RC的名称,全局唯一name: mysql
spec:# Pod副本的期待数量replicas: 1selector:# 符合目标的Pod拥有此标签app: mysql# 根据此模板创建Pod的副本(实例)template:metadata:labels:# Pod副本拥有的标签,对应RC的Selectorapp: mysqlspec:# Pod内容器的定义部分containers:# 容器的名称- name: mysql# 容器对应的Docker Imageimage: mysql:5.7ports:# 容器应用监听的端口号- containerPort: 3306# 注入容器内的环境变量env:- name: MYSQL_ROOT_PASSWORDvalue: "123456"

以上 YAML 定义文件中的 kind 属性用来表明此资源对象的类型,比如这里的值为 ReplicationController,表示这

是一个 RC ;在 spec 一节中是 RC 的相关属性定义,比如 spec.selector 是 RC 的 Pod 标签选择器,即监控和管

理拥有这些标签的 Pod 实例,确保在当前集群中始终有且仅有 replicas 个 Pod 实例在运行,这里设置

replicas=1,表示只能运行一个 MySQL Pod 实例。当在集群中运行的 Pod 数量少于 replicas 时,RC 会根据在

spec.template 一节中定义的 Pod 模板来生成一个新的 Pod 实例,spec.template.metadata.labels 指定了该

Pod 的标签,需要特别注意的是:这里的 labels 必须匹配之前的 spec.selector,否则此 RC 每创建一个无法匹配

Label 的 Pod,就会不停地尝试创建新的 Pod,陷入恶性循环中。

在创建好 mysql-rc.yaml 文件后,将它发布到 kubernetes 集群中,我们在 master 上执行如下命令:

[root@master cha1]# kubectl create -f mysql-rc.yaml
replicationcontroller/mysql created

接下来,用 kubectl 命令查看刚刚创建的 RC:

[root@master cha1]# kubectl get rc -o wide
NAME    DESIRED   CURRENT   READY   AGE     CONTAINERS   IMAGES                    SELECTOR
mysql   1         1         1       7m37s   mysql        mysql:5.7                 app=mysql

查看 Pod 的创建情况时,可以运行下面的命令:

# NODE=slave2表示该pod在slave2节点上创建
[root@master cha1]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE    IP               NODE     NOMINATED NODE   READINESS GATES
mysql-8mwkz   1/1     Running   0          8m8s   10.244.140.65    slave2   <none>           <none>

我们看到一个名为 mysql-8mwkz 的 Pod 实例,这是 kubernetes 根据 mysql 这个 RC 的定义自动创建的 Pod。

由于 Pod 的调度和创建需要花费一定的时间,比如需要一定的时间来确定调度到哪个节点上,以及下载 Pod 里的

容器镜像需要一段时间,所以我们一开始看到Pod的状态显示为 Pending。在 Pod 成功创建完成以后,状态最终

会被更新为 Running。

我们通过 docker ps 指令查看正在运行的容器,发现提供 MySQL 服务的 Pod 容器已经创建并正常运行了,此外

会发现 MySQL Pod 对应的容器还多创建了一个来自谷歌的 pause 容器,这就是 Pod 的根容器。

[root@slave2 ~]# docker ps | grep mysql
9b799e33f346   c20987f18b13                                          "docker-entrypoint.s…"   7 minutes ago    Up 7 minutes              k8s_mysql_mysql-8mwkz_default_b494d65f-2ee8-436b-8a09-ef0b220ba916_0
d18de886ae4e   registry.aliyuncs.com/google_containers/pause:3.4.1   "/pause"                 7 minutes ago    Up 7 minutes              k8s_POD_mysql-8mwkz_default_b494d65f-2ee8-436b-8a09-ef0b220ba916_85

创建一个与之关联的 kubernetes service,service 的定义文件 mysql-svc.yaml如下:

apiVersion: v1
# 表明是Kubernetes Service
kind: Service
metadata:# Service的全局唯一名称name: mysql
spec:ports:# Service提供服务的端口号- port: 3306# Service对应的Pod拥有这里定义的标签selector:app: mysql

其中,metadata.name 是 Service 的服务名;port 属性则定义了 Service 的端口;spec.selector 确定了哪些 Pod

副本(实例)对应本服务。通过下面的命令创建 service:

[root@master cha1]# kubectl create -f mysql-svc.yaml
service/mysql created

运行 kubectl 命令查看刚刚创建的 Service:

[root@master cha1]# kubectl get svc -o wide
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE     SELECTOR
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          15m     <none>
mysql        ClusterIP   10.110.148.221   <none>        3306/TCP         7m12s   app=mysql

可以发现,MySQL 服务被分配了一个值为 10.110.148.221 的 Cluster IP 地址。随后,Kubernetes 集群中其他

新创建的 Pod 就可以通过 Service 的 Cluster IP+端口号3306 来连接和访问它了。

通常,Cluster IP 是在 Service 创建后由 Kubernetes 系统自动分配的,其他 Pod 无法预先知道某个 Service 的

Cluster IP地址,因此需要一个服务发现机制来找到这个服务。为此,最初时,Kubernetes 巧妙地使用了 Linux

环境变量来解决这个问题。现在只需知道,根据 Service 的唯一名称,容器可以从环境变量中获取 Service 对应的

Cluster IP 地址和端口,从而发起 TCP/IP 连接请求。

3、启动Tomcat应用

上面定义和启动了 MySQL 服务,接下来采用同样的步骤完成 Tomcat 应用的启动过程。首先,创建对应的 RC 文

myweb-rc.yaml,内容如下:

apiVersion: v1
# 副本控制器RC
kind: ReplicationController
metadata:# RC的名称,全局唯一name: myweb
spec:# Pod副本的期待数量replicas: 2selector:# 符合目标的Pod拥有此标签app: myweb# 根据此模板创建Pod的副本(实例)template:metadata:labels:# Pod副本拥有的标签,对应RC的Selectorapp: mywebspec:# Pod内容器的定义部分containers:# 容器的名称- name: myweb# 容器对应的 Docker Imageimage: kubeguide/tomcat-app:v1ports:# 容器应用监听的端口号- containerPort: 8080env:- name: MYSQL_SERVICE_HOSTvalue: 'mysql'- name: MYSQL_SERVICE_PORTvalue: '3306'

注意:在 Tomcat 容器内,应用将使用环境变量 MYSQL_SERVICE_HOST 的值连接MySQL服务。更安全可靠的用

法是使用服务的名称 mysql。运行下面的命令,完成RC的创建和验证工作:

[root@master cha1]# kubectl create -f myweb-rc.yaml
replicationcontroller/myweb created
[root@master cha1]# kubectl get pods -o wide
NAME          READY   STATUS    RESTARTS   AGE     IP               NODE     NOMINATED NODE   READINESS GATES
mysql-8mwkz   1/1     Running   0          10m     10.244.140.65    slave2   <none>           <none>
myweb-clht2   1/1     Running   0          8m18s   10.244.140.193   slave1   <none>           <none>
myweb-sjdhr   1/1     Running   0          8m18s   10.244.140.194   slave1   <none>           <none>

最后,创建对应的 Service,定义文件 myweb-svc.yaml

apiVersion: v1
# 表明是Kubernetes Service
kind: Service
metadata:# Service的全局唯一名称name: myweb
spec:type: NodePortports:# Service提供服务的端口号- port: 8080nodePort: 30001# Service对应的Pod拥有这里定义的标签selector:app: myweb

type=NodePort 和 nodePort=30001 的两个属性表明此 Service 开启了 NodePort 方式的外网访问模式。在

Kubernetes 集群之外,比如在本机的浏览器里,可以通过 30001 这个端口访问myweb(对应到8080的虚端口

上)。使用下面的命令进行创建:

[root@master cha1]# kubectl create -f myweb-svc.yaml
service/myweb created

查看 service:

[root@master cha1]# kubectl get svc -o wide
NAME         TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE     SELECTOR
kubernetes   ClusterIP   10.96.0.1        <none>        443/TCP          17m     <none>
mysql        ClusterIP   10.110.148.221   <none>        3306/TCP         8m55s   app=mysql
myweb        NodePort    10.101.194.99    <none>        8080:30001/TCP   8m33s   app=myweb

至此,我们的第1个 Kubernetes 例子便搭建完成了。

4、通过浏览器访问网页

经过上面的几个步骤,我们终于成功实现了 Kubernetes 上第1个例子的部署搭建工作。现在一起来见证成果吧!

打开浏览器输入http://192.168.43.201:30001/demo/,可以看到如下图所示的网页界面:

在这里插入图片描述

接下来,可以尝试单击 Add… 按钮添加一条记录并提交,如图所示,在提交以后,数据就被写入 MySQL 数据库

中了。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

至此,我们终于完成了 Kubernetes 上的 Tomcat 例子,这个例子并不是很复杂。我们也看到,相对于传统的分布

式应用的部署方式,在 Kubernetes 之上我们仅仅通过一些很容易理解的配置文件和相关的简单命令就完成了对整

个集群的部署,这让我们惊诧于 Kubernetes 的创新和强大。


http://www.ppmy.cn/news/535934.html

相关文章

975-操作系统内存管理课件(2)

基本分页存储管理 基本地址变换结构 具有快表的地址变换结构 两级页表

输入一个三位整数,输出由其个位、十位、百位反序而成的三位整数(例如:579反序为975)。

/*------------------------------------------------------- 程序功能&#xff1a;输入一个三位整数&#xff0c;输出由其个位、十位、百位反序而成的三位整数&#xff08;例如&#xff1a;579反序为975&#xff09;。 -----------------------------------------------------…

975: 统计利用先序遍历创建的二叉树的度为2的结点个数

题目描述 利用先序递归遍历算法创建二叉树并计算该二叉树度为2结点的个数。先序递归遍历建立二叉树的方法为&#xff1a;按照先序递归遍历的思想将对二叉树结点的抽象访问具体化为根据接收的数据决定是否产生该结点从而实现创建该二叉树的二叉链表存储结构。约定二叉树结点数据…

975. 只有2个按键的键盘

/* 初始时在记事本上只有一个字符 ‘A’。你可以在此记事本上每一步可以进行两种操作&#xff1a; Copy All: 你可以复制记事本上所有的字符&#xff08;不允许部分复制&#xff09;Paste: 你可以粘贴上一次复制的字符。给出一个数字 n。你需要在记事本上得到恰好 n 个 A&#…

南阳理工---题目975关于521

关于521 时间限制&#xff1a; 1000 ms | 内存限制&#xff1a; 65535 KB 难度&#xff1a; 2 描述 Acm队的流年对数学的研究不是很透彻&#xff0c;但是固执的他还是想一头扎进去。 浏览网页的流年忽然看到了网上有人用玫瑰花瓣拼成了521三个数字&#xff0c;顿时觉得好浪漫…

Leetcode_二分 975.奇偶跳

975.奇偶跳 //二分搜索 O(nlogn) O(n) int oddEvenJumps(vector<int>& A) {const int nA.size();vector<vector<int> > dp(n,vector<int>(2));dp[n-1][0]dp[n-1][1]1;map<int,int> mp; //<value,index> BSTmp[A[n-1]]n-1;int ans…

2018年排名Top 100的Java类库——在分析了277,975份源码之后得出的结论

最近&#xff0c;OveOps公布了The Top 100 Java Libraries in 2018 - Based on 277,975 Source Files&#xff0c;Hollis查看了这份榜单&#xff0c;做了翻译和补充&#xff0c;向你展示2018年的风云Java类库&#xff0c;希望可以给正在使用Java的你一些帮助和启示。不能说榜单…

【简单题string】A. Aramic script(Codeforces Problem-975A)

A. Aramic script codeforces题目链接Problem-975A 题意&#xff1a; 输入n个字符串&#xff0c;对每个字符串去重后&#xff0c;就是一个根对象&#xff0c;输出有多少根对象。比如样例一&#xff0c;a,aa,aaa,ab,abb&#xff0c;去重后的是字符串是a,a,a,ab,ab。所以只有a,a…