เริ่มต้นกับ Kubernetes บน CentOS 7

Kubernetesเป็นแพลตฟอร์มโอเพนซอร์ซที่พัฒนาโดย Google สำหรับการจัดการแอพพลิเคชั่นคอนเทนเนอร์ข้ามคลัสเตอร์เซิร์ฟเวอร์ มันสร้างต่อเมื่อทศวรรษที่ผ่านมาและครึ่งหนึ่งของประสบการณ์ที่ Google มีกับการใช้งานกลุ่มของคอนเทนเนอร์ในระดับและให้นักพัฒนาที่มีโครงสร้างพื้นฐานสไตล์ของ Google ใช้ประโยชน์จากโครงการโอเพนซอร์สที่ดีที่สุดเช่น:

  • นักเทียบท่า : เทคโนโลยีแอปพลิเคชันคอนเทนเนอร์
  • Etcd : ที่เก็บข้อมูลคีย์ - ค่าแบบกระจายที่จัดการข้อมูลทั่วทั้งคลัสเตอร์และให้บริการค้นหาข้อมูล
  • ผ้าสักหลาด : ผ้าเครือข่ายซ้อนทับทำให้การเชื่อมต่อคอนเทนเนอร์ผ่านเซิร์ฟเวอร์หลายเครื่อง

Kubernetes ช่วยให้นักพัฒนาสามารถกำหนดโครงสร้างพื้นฐานแอปพลิเคชันของตนได้อย่างชัดเจนผ่านไฟล์ YAML และ abstractions เช่น Pods, RC และบริการ (เพิ่มเติมในภายหลัง) และทำให้มั่นใจได้ว่าคลัสเตอร์พื้นฐานตรงกับสถานะที่ผู้ใช้กำหนดตลอดเวลา

คุณลักษณะบางอย่างของมันรวมถึง:

  • การกำหนดตารางเวลาอัตโนมัติของทรัพยากรระบบและการวางอัตโนมัติของแอปพลิเคชั่นคอนเทนเนอร์ข้ามคลัสเตอร์
  • ปรับแอพพลิเคชั่นได้ทันทีด้วยคำสั่งเดียว
  • การอัพเดทแบบโรลลิ่งโดยไม่มีการหยุดทำงาน
  • การรักษาตัวเอง: กำหนดเวลาใหม่โดยอัตโนมัติของแอปพลิเคชันหากเซิร์ฟเวอร์ล้มเหลวรีสตาร์ทคอนเทนเนอร์โดยอัตโนมัติตรวจสอบสุขภาพ

ข้ามไปยังการติดตั้งล่วงหน้าหากคุณคุ้นเคยกับ Kubernetes แล้ว

แนวคิดพื้นฐาน

Kubernetes เสนอ abstractions (หน่วยทางลอจิคัล) ต่อไปนี้สำหรับนักพัฒนา:

  • ฝัก
  • ตัวควบคุมการจำลองแบบ
  • ป้ายกำกับ
  • บริการ

ฝัก

เป็นหน่วยพื้นฐานของ Kubernetes ปริมาณงาน พ็อดจำลองโมเดล "โลจิคัลโฮสต์" เฉพาะแอ็พพลิเคชันในสภาพแวดล้อมแบบคอนเทนเนอร์ ในแง่คนธรรมดามันรุ่นกลุ่มของโปรแกรมหรือบริการที่ใช้ในการทำงานบนเซิร์ฟเวอร์เดียวกันในโลกก่อนภาชนะ ภาชนะภายในฝักแบ่งใช้เนมสเปซเครือข่ายเดียวกันและสามารถแบ่งปันปริมาณข้อมูลได้เช่นกัน

ตัวควบคุมการจำลองแบบ

พ็อดดีเยี่ยมสำหรับการจัดกลุ่มคอนเทนเนอร์จำนวนมากไว้ในหน่วยแอปพลิเคชันเชิงตรรกะ แต่ไม่ได้เสนอการจำลองแบบหรือกำหนดเวลาใหม่ในกรณีที่เซิร์ฟเวอร์ล้มเหลว

นี่คือที่ตัวควบคุมการจำลองแบบหรือ RC มีประโยชน์ RC ตรวจสอบให้แน่ใจว่ามีจำนวนพ็อดของบริการที่กำหนดให้ทำงานอยู่ตลอดเวลาในคลัสเตอร์

ป้ายกำกับ

เป็นข้อมูลเมตาของคีย์ - ค่าที่สามารถแนบกับทรัพยากร Kubernetes ใด ๆ (พ็อด, RCs, บริการ, โหนด, ... )

บริการ

ตัวควบคุม Pod และการจำลองแบบนั้นยอดเยี่ยมสำหรับการปรับใช้และการกระจายแอปพลิเคชันในคลัสเตอร์ แต่พ็อดมี IP แบบชั่วคราวที่เปลี่ยนแปลงเมื่อกำหนดเวลาใหม่หรือรีสตาร์ทคอนเทนเนอร์

บริการ Kubernetes จัดเตรียมจุดปลายที่เสถียร (IP เสมือน + พอร์ตที่เชื่อมกับเซิร์ฟเวอร์โฮสต์คงที่) สำหรับกลุ่มของพ็อดที่จัดการโดยคอนโทรลเลอร์การจำลอง

คลัสเตอร์ Kubernetes

ในรูปแบบที่ง่ายที่สุดคลัสเตอร์ Kubernetes ประกอบด้วยโหนดสองประเภท:

  • 1 Kubernetes master
  • โหนดN Kubernetes

ต้นแบบ Kubernetes

ต้นแบบ Kubernetes เป็นหน่วยควบคุมของทั้งคลัสเตอร์

ส่วนประกอบหลักของต้นแบบคือ:

  • Etcd: ดาต้าสโตร์ที่มีอยู่ทั่วโลกที่เก็บข้อมูลเกี่ยวกับคลัสเตอร์และบริการและแอปพลิเคชันที่ทำงานบนคลัสเตอร์
  • เซิร์ฟเวอร์ Kube API: นี่เป็นฮับการจัดการหลักของคลัสเตอร์ Kubernetes และจะเปิดเผยอินเตอร์เฟส RESTful
  • ตัวจัดการคอนโทรลเลอร์: จัดการการจำลองของแอปพลิเคชันที่จัดการโดยตัวควบคุมการจำลอง
  • Scheduler: ติดตามการใช้ทรัพยากรทั่วทั้งคลัสเตอร์และกำหนดปริมาณงานให้สอดคล้อง

โหนด Kubernetes

โหนด Kubernetes เป็นเซิร์ฟเวอร์ผู้ปฏิบัติงานที่รับผิดชอบการเรียกใช้พ็อด

ส่วนประกอบหลักของโหนดคือ:

  • นักเทียบท่า: daemon ที่รันคอนเทนเนอร์แอปพลิเคชันที่กำหนดในพ็อด
  • Kubelet: ชุดควบคุมสำหรับพ็อดในระบบท้องถิ่น
  • Kube-proxy: เครือข่ายพร็อกซี่ที่รับรองการกำหนดเส้นทางที่ถูกต้องสำหรับบริการ Kubernetes

การติดตั้ง

ในคู่มือนี้เราจะสร้างคลัสเตอร์ 3 โหนดโดยใช้เซิร์ฟเวอร์ CentOS 7:

  • 1 Kubernetes master (kube-master)
  • 2 โหนด Kubernetes (kube-node1, kube-node2)

คุณสามารถเพิ่มโหนดพิเศษได้มากเท่าที่คุณต้องการในภายหลังโดยทำตามขั้นตอนการติดตั้งเดียวกันสำหรับโหนด Kubernetes

โหนดทั้งหมด

กำหนดค่าชื่อโฮสต์และ/etc/hosts:

# /etc/hostname
kube-master
# or kube-node1, kube-node2

# append to /etc/hosts
replace-with-master-server-ip kube-master
replace-with-node1-ip kube-node1
replace-with-node2-ip kube-node2

ปิดการใช้งาน firewalld:

systemctl disable firewalld
systemctl stop firewalld

ต้นแบบ Kubernetes

ติดตั้งแพคเกจต้นแบบ Kubernetes:

yum install etcd kubernetes-master

การกำหนดค่า:

# /etc/etcd/etcd.conf
# leave rest of the lines unchanged
ETCD_LISTEN_CLIENT_URLS="http://0.0.0.0:2379"
ETCD_LISTEN_PEER_URLS="http://localhost:2380"
ETCD_ADVERTISE_CLIENT_URLS="http://0.0.0.0:2379"

# /etc/kubernetes/config
# leave rest of the lines unchanged
KUBE_MASTER="--master=http://kube-master:8080"

# /etc/kubernetes/apiserver
# leave rest of the lines unchanged
KUBE_API_ADDRESS="--address=0.0.0.0"
KUBE_ETCD_SERVERS="--etcd_servers=http://kube-master:2379"

เริ่ม Etcd:

systemctl start etcd

ติดตั้งและกำหนดค่าโครงข่ายเครือข่าย Flannel overlay (จำเป็นต้องมีเพื่อให้คอนเทนเนอร์ที่ทำงานบนเซิร์ฟเวอร์ที่แตกต่างกันสามารถมองเห็นซึ่งกันและกัน):

yum install flannel

สร้างไฟล์กำหนดค่า Flannel ( flannel-config.json):

{
  "Network": "10.20.0.0/16",
  "SubnetLen": 24,
  "Backend": {
    "Type": "vxlan",
    "VNI": 1
  }  
}

ตั้งค่าการกำหนดค่า Flannel ในเซิร์ฟเวอร์ Etcd:

etcdctl set coreos.com/network/config < flannel-config.json

ชี้ Flannel ไปยังเซิร์ฟเวอร์ Etcd:

# /etc/sysconfig/flanneld
FLANNEL_ETCD="http://kube-master:2379"

เปิดใช้งานบริการเพื่อให้พวกเขาเริ่มต้นในการบูต:

systemctl enable etcd
systemctl enable kube-apiserver
systemctl enable kube-controller-manager
systemctl enable kube-scheduler
systemctl enable flanneld

รีบูตเซิร์ฟเวอร์

โหนด Kubernetes

ติดตั้งแพ็กเกจโหนด Kubernetes:

yum install docker kubernetes-node

สองขั้นตอนถัดไปจะกำหนดค่า Docker ให้ใช้โอเวอร์เลย์เพื่อประสิทธิภาพที่ดีขึ้น สำหรับข้อมูลเพิ่มเติมโปรดเยี่ยมชมโพสต์บล็อกนี้ :

ลบไดเร็กทอรีหน่วยเก็บข้อมูล docker ปัจจุบัน:

systemctl stop docker
rm -rf /var/lib/docker

เปลี่ยนไฟล์การกำหนดค่า:

# /etc/sysconfig/docker
# leave rest of lines unchanged
OPTIONS='--selinux-enabled=false'

# /etc/sysconfig/docker
# leave rest of lines unchanged
DOCKER_STORAGE_OPTIONS=-s overlay

กำหนดค่า kube-node1 เพื่อใช้ต้นแบบที่กำหนดค่าไว้ก่อนหน้านี้ของเรา:

# /etc/kubernetes/config
# leave rest of lines unchanged
KUBE_MASTER="--master=http://kube-master:8080"

# /etc/kubernetes/kubelet
# leave rest of the lines unchanged
KUBELET_ADDRESS="--address=0.0.0.0"
# comment this line, so that the actual hostname is used to register the node
# KUBELET_HOSTNAME="--hostname_override=127.0.0.1"
KUBELET_API_SERVER="--api_servers=http://kube-master:8080"

ติดตั้งและกำหนดค่าเครือข่ายซ้อนทับ Flannel (อีกครั้ง - นี่เป็นสิ่งจำเป็นเพื่อให้คอนเทนเนอร์ที่ทำงานบนเซิร์ฟเวอร์ที่แตกต่างกันสามารถเห็นกัน):

yum install flannel

ชี้ Flannel ไปยังเซิร์ฟเวอร์ Etcd:

# /etc/sysconfig/flanneld
FLANNEL_ETCD="http://kube-master:2379"

เปิดใช้งานบริการ:

systemctl enable docker
systemctl enable flanneld
systemctl enable kubelet
systemctl enable kube-proxy

รีบูตเซิร์ฟเวอร์

ทดสอบเซิร์ฟเวอร์ Kubernetes ของคุณ

หลังจากเซิร์ฟเวอร์ทั้งหมดรีบูตตรวจสอบว่าคลัสเตอร์ Kubernetes ของคุณทำงานอยู่หรือไม่:

[root@kube-master ~]# kubectl get nodes
NAME         LABELS                              STATUS
kube-node1   kubernetes.io/hostname=kube-node1   Ready
kube-node2   kubernetes.io/hostname=kube-node2   Ready

ตัวอย่าง: การปรับใช้กริดซีลีเนียมโดยใช้ Kubernetes

ซีลีเนียมเป็นกรอบการทำงานสำหรับเบราว์เซอร์อัตโนมัติเพื่อการทดสอบ มันเป็นเครื่องมืออันทรงพลังของคลังแสงของผู้พัฒนาเว็บใด ๆ

ตารางซีลีเนียมช่วยให้สามารถทำการทดสอบระยะไกลแบบขนานและแบบขนานในคลัสเตอร์ของโหนดซีลีเนียมที่เชื่อมต่อกับฮับซีลีเนียมส่วนกลาง

เนื่องจากโหนดซีลีเนียมนั้นไร้สัญชาติและจำนวนโหนดที่เรารันนั้นมีความยืดหยุ่นขึ้นอยู่กับปริมาณงานทดสอบของเรานี่เป็นแอปพลิเคชั่นที่สมบูรณ์แบบที่จะนำไปใช้ในคลัสเตอร์ Kubernetes

ในส่วนถัดไปเราจะปรับใช้กริดซึ่งประกอบด้วย 5 คอนเทนเนอร์ของแอปพลิเคชัน:

  • ศูนย์กลางฮับซีลีเนียม 1 แห่งซึ่งจะเป็นจุดปลายทางระยะไกลซึ่งการทดสอบของเราจะเชื่อมต่อ
  • 2 ซีลีเนียมโหนดที่ใช้ Firefox
  • 2 ซีลีเนียมโหนดที่ใช้งาน Chrome

กลยุทธ์การปรับใช้

ในการจัดการการจำลองแบบและการแก้ไขตัวเองโดยอัตโนมัติเราจะสร้างตัวควบคุมการจำลองแบบ Kubernetes สำหรับแต่ละประเภทของแอปพลิเคชันคอนเทนเนอร์ที่เราแสดงไว้ข้างต้น

เพื่อให้นักพัฒนาที่กำลังรันการทดสอบด้วยจุดสิ้นสุดฮับ Selenium ที่เสถียรเราจะสร้างบริการ Kubernetes ที่เชื่อมต่อกับตัวควบคุมการจำลองแบบฮับ

ซีลีเนียมฮับ

ตัวควบคุมการจำลองแบบ
# selenium-hub-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: selenium-hub
spec:
  replicas: 1
  selector:
    name: selenium-hub
  template:
    metadata:
      labels:
        name: selenium-hub
    spec:
      containers:
        - name: selenium-hub
          image: selenium/hub
          ports:
            - containerPort: 4444

การใช้งาน:

[root@kube-master ~]# kubectl create -f selenium-hub-rc.yaml
replicationcontrollers/selenium-hub
[root@kube-master ~]# kubectl get rc
CONTROLLER     CONTAINER(S)   IMAGE(S)       SELECTOR            REPLICAS
selenium-hub   selenium-hub   selenium/hub   name=selenium-hub   1
[root@kube-master ~]# kubectl get pods
NAME                 READY     STATUS    RESTARTS   AGE
selenium-hub-pilc8   1/1       Running   0          50s
[root@kube-master ~]# kubectl describe pod selenium-hub-pilc8
Name:               selenium-hub-pilc8
Namespace:          default
Image(s):           selenium/hub
Node:               kube-node2/45.63.16.92
Labels:             name=selenium-hub
Status:             Running
Reason:             
Message:            
IP:             10.20.101.2
Replication Controllers:    selenium-hub (1/1 replicas created)
Containers:
  selenium-hub:
    Image:      selenium/hub
    State:      Running
      Started:      Sat, 24 Oct 2015 16:01:39 +0000
    Ready:      True
    Restart Count:  0
Conditions:
  Type      Status
  Ready     True
Events:
  FirstSeen             LastSeen            Count   From            SubobjectPath               Reason      Message
  Sat, 24 Oct 2015 16:01:02 +0000   Sat, 24 Oct 2015 16:01:02 +0000 1   {scheduler }                            scheduled   Successfully assigned selenium-hub-pilc8 to kube-node2
  Sat, 24 Oct 2015 16:01:05 +0000   Sat, 24 Oct 2015 16:01:05 +0000 1   {kubelet kube-node2}    implicitly required container POD   pulled      Successfully pulled Pod container image "gcr.io/google_containers/pause:0.8.0"
  Sat, 24 Oct 2015 16:01:05 +0000   Sat, 24 Oct 2015 16:01:05 +0000 1   {kubelet kube-node2}    implicitly required container POD   created     Created with docker id 6de00106b19c
  Sat, 24 Oct 2015 16:01:05 +0000   Sat, 24 Oct 2015 16:01:05 +0000 1   {kubelet kube-node2}    implicitly required container POD   started     Started with docker id 6de00106b19c
  Sat, 24 Oct 2015 16:01:39 +0000   Sat, 24 Oct 2015 16:01:39 +0000 1   {kubelet kube-node2}    spec.containers     pulled      Successfully pulled image "selenium/hub"
  Sat, 24 Oct 2015 16:01:39 +0000   Sat, 24 Oct 2015 16:01:39 +0000 1   {kubelet kube-node2}    spec.containers     created     Created with docker id 7583cc09268c
  Sat, 24 Oct 2015 16:01:39 +0000   Sat, 24 Oct 2015 16:01:39 +0000 1   {kubelet kube-node2}    spec.containers     started     Started with docker id 7583cc09268c

ที่นี่เราจะเห็นได้ว่า Kubernetes วางคอนเทนเนอร์ซีลีเนียมฮับของฉันไว้ที่ kube-node2

บริการ
# selenium-hub-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: selenium-hub
spec:
  type: NodePort
  ports:
  - port: 4444
    protocol: TCP
    nodePort: 30000
  selector:
    name: selenium-hub

การใช้งาน:

[root@kube-master ~]# kubectl create -f selenium-hub-service.yaml
You have exposed your service on an external port on all nodes in your
cluster.  If you want to expose this service to the external internet, you may
need to set up firewall rules for the service port(s) (tcp:30000) to serve traffic.

See http://releases.k8s.io/HEAD/docs/user-guide/services-firewalls.md for more details.
services/selenium-hub
[root@kube-master ~]# kubectl get services
NAME           LABELS                                    SELECTOR            IP(S)           PORT(S)
kubernetes     component=apiserver,provider=kubernetes   <none>              10.254.0.1      443/TCP
selenium-hub   <none>                                    name=selenium-hub   10.254.124.73   4444/TCP

หลังจากปรับใช้บริการจะสามารถเข้าถึงได้จาก:

  • โหนด Kubernetes ใด ๆ ผ่าน IP เสมือน 10.254.124.73 และพอร์ต 4444
  • เครือข่ายภายนอกผ่าน IP สาธารณะของโหนด Kubernetes ใด ๆ บนพอร์ต 30000

เริ่มต้นกับ Kubernetes บน CentOS 7เริ่มต้นกับ Kubernetes บน CentOS 7 (ใช้ IP สาธารณะของโหนด Kubernetes อื่น)

โหนดซีลีเนียม

ตัวควบคุมการจำลองแบบของโหนด Firefox:

# selenium-node-firefox-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: selenium-node-firefox
spec:
  replicas: 2
  selector:
    name: selenium-node-firefox
  template:
    metadata:
      labels:
        name: selenium-node-firefox
    spec:
      containers:
        - name: selenium-node-firefox
          image: selenium/node-firefox
          ports:
            - containerPort: 5900
          env:
            - name: HUB_PORT_4444_TCP_ADDR
              value: "replace_with_service_ip"
            - name: HUB_PORT_4444_TCP_PORT
              value: "4444"

การใช้งาน:

แทนที่replace_with_service_ipในselenium-node-firefox-rc.yamlกับ IP บริการซีลีเนียมศูนย์กลางที่เกิดขึ้นจริงในกรณีนี้ 10.254.124.73

[root@kube-master ~]# kubectl create -f selenium-node-firefox-rc.yaml
replicationcontrollers/selenium-node-firefox

[root@kube-master ~]# kubectl get rc
CONTROLLER              CONTAINER(S)            IMAGE(S)                SELECTOR                     REPLICAS
selenium-hub            selenium-hub            selenium/hub            name=selenium-hub            1
selenium-node-firefox   selenium-node-firefox   selenium/node-firefox   name=selenium-node-firefox   2

[root@kube-master ~]# kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
selenium-hub-pilc8            1/1       Running   1          1h
selenium-node-firefox-lc6qt   1/1       Running   0          2m
selenium-node-firefox-y9qjp   1/1       Running   0          2m

[root@kube-master ~]# kubectl describe pod selenium-node-firefox-lc6qt
Name:               selenium-node-firefox-lc6qt
Namespace:          default
Image(s):           selenium/node-firefox
Node:               kube-node2/45.63.16.92
Labels:             name=selenium-node-firefox
Status:             Running
Reason:             
Message:            
IP:             10.20.101.3
Replication Controllers:    selenium-node-firefox (2/2 replicas created)
Containers:
  selenium-node-firefox:
    Image:      selenium/node-firefox
    State:      Running
      Started:      Sat, 24 Oct 2015 17:08:37 +0000
    Ready:      True
    Restart Count:  0
Conditions:
  Type      Status
  Ready     True
Events:
  FirstSeen             LastSeen            Count   From            SubobjectPath               Reason      Message
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {scheduler }                            scheduled   Successfully assigned selenium-node-firefox-lc6qt to kube-node2
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node2}    implicitly required container POD   pulled      Pod container image "gcr.io/google_containers/pause:0.8.0" already present on machine
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node2}    implicitly required container POD   created     Created with docker id cdcb027c6548
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node2}    implicitly required container POD   started     Started with docker id cdcb027c6548
  Sat, 24 Oct 2015 17:08:36 +0000   Sat, 24 Oct 2015 17:08:36 +0000 1   {kubelet kube-node2}    spec.containers pulled      Successfully pulled image "selenium/node-firefox"
  Sat, 24 Oct 2015 17:08:36 +0000   Sat, 24 Oct 2015 17:08:36 +0000 1   {kubelet kube-node2}    spec.containers created     Created with docker id 8931b7f7a818
  Sat, 24 Oct 2015 17:08:37 +0000   Sat, 24 Oct 2015 17:08:37 +0000 1   {kubelet kube-node2}    spec.containers started     Started with docker id 8931b7f7a818

[root@kube-master ~]# kubectl describe pod selenium-node-firefox-y9qjp
Name:               selenium-node-firefox-y9qjp
Namespace:          default
Image(s):           selenium/node-firefox
Node:               kube-node1/185.92.221.67
Labels:             name=selenium-node-firefox
Status:             Running
Reason:             
Message:            
IP:             10.20.92.3
Replication Controllers:    selenium-node-firefox (2/2 replicas created)
Containers:
  selenium-node-firefox:
    Image:      selenium/node-firefox
    State:      Running
      Started:      Sat, 24 Oct 2015 17:08:13 +0000
    Ready:      True
    Restart Count:  0
Conditions:
  Type      Status
  Ready     True
Events:
  FirstSeen             LastSeen            Count   From            SubobjectPath               Reason      Message
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {scheduler }                            scheduled   Successfully assigned selenium-node-firefox-y9qjp to kube-node1
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node1}    implicitly required container POD   pulled      Pod container image "gcr.io/google_containers/pause:0.8.0" already present on machine
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node1}    implicitly required container POD   created     Created with docker id ea272dd36bd5
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node1}    implicitly required container POD   started     Started with docker id ea272dd36bd5
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node1}    spec.containers created     Created with docker id 6edbd6b9861d
  Sat, 24 Oct 2015 17:08:13 +0000   Sat, 24 Oct 2015 17:08:13 +0000 1   {kubelet kube-node1}    spec.containers started     Started with docker id 6edbd6b9861d

อย่างที่เราเห็น Kubernetes สร้าง 2 replicas selenium-firefox-nodeและมันแจกจ่ายไปทั่วทั้งคลัสเตอร์ Pod selenium-node-firefox-lc6qtอยู่บน kube-node2 ในขณะที่ pod selenium-node-firefox-y9qjpอยู่บน kube-node1

เราทำซ้ำกระบวนการเดียวกันสำหรับโหนดซีลีเนียม Chrome

ตัวควบคุมการจำลองแบบโหนดของ Chrome:

# selenium-node-chrome-rc.yaml
apiVersion: v1
kind: ReplicationController
metadata:
  name: selenium-node-chrome
  labels:
    app: selenium-node-chrome
spec:
  replicas: 2
  selector:
    app: selenium-node-chrome
  template:
    metadata:
      labels:
        app: selenium-node-chrome
    spec:
      containers:
      - name: selenium-node-chrome
        image: selenium/node-chrome
        ports:
          - containerPort: 5900
        env:
          - name: HUB_PORT_4444_TCP_ADDR
            value: "replace_with_service_ip"
          - name: HUB_PORT_4444_TCP_PORT
            value: "4444"

การใช้งาน:

[root@kube-master ~]# kubectl create -f selenium-node-chrome-rc.yaml
replicationcontrollers/selenium-node-chrome
[root@kube-master ~]# kubectl get rc
CONTROLLER              CONTAINER(S)            IMAGE(S)                SELECTOR                     REPLICAS
selenium-hub            selenium-hub            selenium/hub            name=selenium-hub            1
selenium-node-chrome    selenium-node-chrome    selenium/node-chrome    app=selenium-node-chrome     2
selenium-node-firefox   selenium-node-firefox   selenium/node-firefox   name=selenium-node-firefox   2
[root@kube-master ~]# kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
selenium-hub-pilc8            1/1       Running   1          1h
selenium-node-chrome-9u1ld    1/1       Running   0          1m
selenium-node-chrome-mgi52    1/1       Running   0          1m
selenium-node-firefox-lc6qt   1/1       Running   0          11m
selenium-node-firefox-y9qjp   1/1       Running   0          11m

ห่อ

ในคู่มือนี้เราได้สร้างคลัสเตอร์ Kubernetes ขนาดเล็กของเซิร์ฟเวอร์ 3 เครื่อง (ผู้ควบคุมหลัก 1 คน + พนักงาน 2 คน)

ด้วยการใช้ pods, RC และบริการเราได้ทำการปรับใช้ Selenium Grid ซึ่งประกอบด้วยฮับกลางและ 4 โหนดเพื่อให้นักพัฒนาสามารถรันการทดสอบ Selenium พร้อมกัน 4 ครั้งในคลัสเตอร์

Kubernetes จัดกำหนดการคอนเทนเนอร์โดยอัตโนมัติทั่วทั้งคลัสเตอร์

เริ่มต้นกับ Kubernetes บน CentOS 7

รักษาตัวเอง

Kubernetes ปรับเปลี่ยนพ็อดโดยอัตโนมัติไปยังเซิร์ฟเวอร์ที่มีสุขภาพดีหากเซิร์ฟเวอร์ของเราตั้งแต่หนึ่งตัวขึ้นไป ในตัวอย่างของฉัน kube-node2 กำลังเรียกใช้ฝักฮับซีลีเนียมและโหนดซีลีเนียม Firefox 1 โหนด

[root@kube-node2 ~]# docker ps
CONTAINER ID        IMAGE                                  COMMAND                CREATED             STATUS              PORTS               NAMES
5617399f146c        selenium/node-firefox                  "/opt/bin/entry_poin   5 minutes ago       Up 5 minutes                            k8s_selenium-node-firefox.46e635d8_selenium-node-firefox-zmj1r_default_31c89517-7a75-11e5-8648-5600001611e0_baae8e00   
185230a3b431        gcr.io/google_containers/pause:0.8.0   "/pause"               5 minutes ago       Up 5 minutes                            k8s_POD.3805e8b7_selenium-node-firefox-zmj1r_default_31c89517-7a75-11e5-8648-5600001611e0_40f809df                     
fdd5834c249d        selenium/hub                           "/opt/bin/entry_poin   About an hour ago   Up About an hour                        k8s_selenium-hub.cb8bf0ed_selenium-hub-pilc8_default_6c98c1ff-7a68-11e5-8648-5600001611e0_5765e2c9                     
00e4ccb0bda8        gcr.io/google_containers/pause:0.8.0   "/pause"               About an hour ago   Up About an hour                        k8s_POD.3b3ee8b9_selenium-hub-pilc8_default_6c98c1ff-7a68-11e5-8648-5600001611e0_8398ac33  

เราจะจำลองความล้มเหลวของเซิร์ฟเวอร์โดยการปิด kube-node2 หลังจากสองสามนาทีคุณควรเห็นว่าคอนเทนเนอร์ที่รันบน kube-node2 ถูกกำหนดตารางเวลาใหม่เป็น kube-node1 เพื่อให้แน่ใจว่าเซอร์วิสหยุดชะงักน้อยที่สุด

[root@kube-node1 ~]# docker ps
CONTAINER ID        IMAGE                                  COMMAND                CREATED             STATUS              PORTS               NAMES
5bad5f582698        selenium/hub                           "/opt/bin/entry_poin   19 minutes ago      Up 19 minutes                           k8s_selenium-hub.cb8bf0ed_selenium-hub-hycf2_default_fe9057cf-7a76-11e5-8648-5600001611e0_ccaad50a                     
dd1565a94919        selenium/node-firefox                  "/opt/bin/entry_poin   20 minutes ago      Up 20 minutes                           k8s_selenium-node-firefox.46e635d8_selenium-node-firefox-g28z5_default_fe932673-7a76-11e5-8648-5600001611e0_fc79f977   
2be1a316aa47        gcr.io/google_containers/pause:0.8.0   "/pause"               20 minutes ago      Up 20 minutes                           k8s_POD.3805e8b7_selenium-node-firefox-g28z5_default_fe932673-7a76-11e5-8648-5600001611e0_dc204ad2                     
da75a0242a9e        gcr.io/google_containers/pause:0.8.0   "/pause"               20 minutes ago      Up 20 minutes                           k8s_POD.3b3ee8b9_selenium-hub-hycf2_default_fe9057cf-7a76-11e5-8648-5600001611e0_1b10c0e7                              
c611b68330de        selenium/node-firefox                  "/opt/bin/entry_poin   33 minutes ago      Up 33 minutes                           k8s_selenium-node-firefox.46e635d8_selenium-node-firefox-8ylo2_default_31c8a8f3-7a75-11e5-8648-5600001611e0_922af821   
828031da6b3c        gcr.io/google_containers/pause:0.8.0   "/pause"               33 minutes ago      Up 33 minutes                           k8s_POD.3805e8b7_selenium-node-firefox-8ylo2_default_31c8a8f3-7a75-11e5-8648-5600001611e0_289cd555                     
caf4e725512e        selenium/node-chrome                   "/opt/bin/entry_poin   46 minutes ago      Up 46 minutes                           k8s_selenium-node-chrome.362a34ee_selenium-node-chrome-mgi52_default_392a2647-7a73-11e5-8648-5600001611e0_3c6e855a     
409a20770787        selenium/node-chrome                   "/opt/bin/entry_poin   46 minutes ago      Up 46 minutes                           k8s_selenium-node-chrome.362a34ee_selenium-node-chrome-9u1ld_default_392a15a4-7a73-11e5-8648-5600001611e0_ac3f0191     
7e2d942422a5        gcr.io/google_containers/pause:0.8.0   "/pause"               47 minutes ago      Up 47 minutes                           k8s_POD.3805e8b7_selenium-node-chrome-9u1ld_default_392a15a4-7a73-11e5-8648-5600001611e0_f5858b73                      
a3a65ea99a99        gcr.io/google_containers/pause:0.8.0   "/pause"               47 minutes ago      Up 47 minutes                           k8s_POD.3805e8b7_selenium-node-chrome-mgi52_default_392a2647-7a73-11e5-8648-5600001611e0_20a70ab6

ปรับขนาด Selenium Grid ของคุณ

การปรับขนาด Selenium Grid นั้นง่ายมากด้วย Kubernetes ลองจินตนาการว่าแทนที่จะเป็น 2 Firefox ผมอยากจะเรียกใช้ 4 การลดอัตราการสุ่มสามารถทำได้ด้วยคำสั่งเดียว:

[root@kube-master ~]# kubectl scale rc selenium-node-firefox --replicas=4
scaled

[root@kube-master ~]# kubectl get rc
CONTROLLER              CONTAINER(S)            IMAGE(S)                SELECTOR                     REPLICAS
selenium-hub            selenium-hub            selenium/hub            name=selenium-hub            1
selenium-node-chrome    selenium-node-chrome    selenium/node-chrome    app=selenium-node-chrome     2
selenium-node-firefox   selenium-node-firefox   selenium/node-firefox   name=selenium-node-firefox   4

[root@kube-master ~]# kubectl get pods
NAME                          READY     STATUS    RESTARTS   AGE
selenium-hub-pilc8            1/1       Running   1          1h
selenium-node-chrome-9u1ld    1/1       Running   0          14m
selenium-node-chrome-mgi52    1/1       Running   0          14m
selenium-node-firefox-8ylo2   1/1       Running   0          40s
selenium-node-firefox-lc6qt   1/1       Running   0          24m
selenium-node-firefox-y9qjp   1/1       Running   0          24m
selenium-node-firefox-zmj1r   1/1       Running   0          40s

เริ่มต้นกับ Kubernetes บน CentOS 7



Leave a Comment

การติดตั้ง Pagekit CMS บน CentOS 7

การติดตั้ง Pagekit CMS บน CentOS 7

ใช้ระบบที่แตกต่างกันอย่างไร Pagekit เป็น CMS โอเพนซอร์สที่เขียนด้วย PHP ซอร์สโค้ดของ Pagekit นั้นโฮสต์บน GitHub คำแนะนำนี้จะแสดงให้คุณเห็นว่า

วิธีการติดตั้ง TestLink บน CentOS 7

วิธีการติดตั้ง TestLink บน CentOS 7

TestLink เป็นระบบดำเนินการจัดการทดสอบบนเว็บโอเพ่นซอร์ส ช่วยให้ทีมงานประกันคุณภาพสามารถสร้างและจัดการกรณีทดสอบได้เช่นกัน

วิธีการที่ปลอดภัย vsFTPd ด้วย SSL / TLS

วิธีการที่ปลอดภัย vsFTPd ด้วย SSL / TLS

FTP ที่ปลอดภัยมากหรือเพียงแค่ vsFTPd เป็นซอฟต์แวร์น้ำหนักเบาที่มีความสามารถในการปรับแต่ง ในบทช่วยสอนนี้เราจะรักษาความปลอดภัยของข้อความ

วิธีการติดตั้ง GCC บน CentOS 6

วิธีการติดตั้ง GCC บน CentOS 6

CentOS ติดตามการพัฒนา Red Hat Enterprise Linux (RHEL) RHEL พยายามที่จะเป็นแพลตฟอร์มเซิร์ฟเวอร์ที่มั่นคงซึ่งหมายความว่าจะไม่รีบเร่งในการรวม

ตั้งค่าบัญชีผู้ใช้ SFTP เท่านั้นบน CentOS 7

ตั้งค่าบัญชีผู้ใช้ SFTP เท่านั้นบน CentOS 7

ในบางโอกาสผู้ดูแลระบบอาจต้องสร้างบัญชีผู้ใช้และ จำกัด การเข้าถึงเพื่อจัดการไฟล์ของตัวเองผ่าน sFTP เท่านั้น

วิธีการติดตั้ง Moodle บน CentOS 7

วิธีการติดตั้ง Moodle บน CentOS 7

ใช้ระบบที่แตกต่างกันอย่างไร Moodle เป็นแพลตฟอร์มการเรียนรู้โอเพนซอร์ซหรือระบบจัดการหลักสูตร (CMS) - ชุดซอฟต์แวร์โอเพ่นซอร์สฟรีที่ออกแบบมาเพื่อช่วย

ติดตั้ง NGINX พร้อม ModSecurity บน CentOS 6

ติดตั้ง NGINX พร้อม ModSecurity บน CentOS 6

ในบทความนี้ฉันจะอธิบายวิธีสร้าง LEMP สแต็คที่ได้รับการป้องกันโดย ModSecurity ModSecurity เป็นไฟร์วอลล์เว็บแอพพลิเคชันแบบโอเพนซอร์สที่มีประโยชน์

วิธีการติดตั้ง Apache, MySQL และ PHP บน CentOS 6

วิธีการติดตั้ง Apache, MySQL และ PHP บน CentOS 6

Introduction LAMP เป็นคำย่อที่ย่อมาจาก Linux, Apache, MySQL และ PHP ซอฟต์แวร์นี้เป็นโซลูชันโอเพ่นซอร์สที่ได้รับความนิยมสูงสุดสำหรับการติดตั้ง o

การปรับเปลี่ยน Icinga2 ให้ใช้โมเดลต้นแบบ / ไคลเอ็นต์บน CentOS 6 หรือ CentOS 7

การปรับเปลี่ยน Icinga2 ให้ใช้โมเดลต้นแบบ / ไคลเอ็นต์บน CentOS 6 หรือ CentOS 7

Icinga2 เป็นระบบการตรวจสอบที่มีประสิทธิภาพและเมื่อใช้ในโมเดลลูกค้าหลักจะสามารถแทนที่ความต้องการการตรวจสอบที่อิง NRPE ปรมาจารย์

การติดตั้ง Netdata บน CentOS 7

การติดตั้ง Netdata บน CentOS 7

ใช้ระบบที่แตกต่างกันอย่างไร Netdata เป็นดาวรุ่งพุ่งแรงในด้านการติดตามการวัดในระบบแบบเรียลไทม์ เมื่อเปรียบเทียบกับเครื่องมือชนิดเดียวกัน Netdata:

วิธีการติดตั้งและกำหนดค่า Buildbot บน CentOS 7

วิธีการติดตั้งและกำหนดค่า Buildbot บน CentOS 7

Buildbot เป็นโอเพ่นซอร์สเครื่องมือที่ใช้การรวมอย่างต่อเนื่องของ Python สำหรับการสร้างซอฟต์แวร์การทดสอบและการปรับใช้โดยอัตโนมัติ Buildbot ประกอบด้วยหนึ่งหรือหมอ

ติดตั้งเซิร์ฟเวอร์มัลติเพลเยอร์ SA-MP San Andreas บน CentOS 6

ติดตั้งเซิร์ฟเวอร์มัลติเพลเยอร์ SA-MP San Andreas บน CentOS 6

ยินดีต้อนรับสู่การกวดวิชา Vultr อื่น ที่นี่คุณจะได้เรียนรู้วิธีการติดตั้งและเรียกใช้เซิร์ฟเวอร์ SAMP คู่มือนี้เขียนขึ้นสำหรับ CentOS 6 ข้อกำหนดเบื้องต้นคุณจะต้อง

ติดตั้ง dotProject บน CentOS 7

ติดตั้ง dotProject บน CentOS 7

แอปพลิเคชั่น dotProject เป็นเครื่องมือการจัดการโครงการแบบโอเพ่นซอร์สบนเว็บ สำหรับตอนนี้มันวางจำหน่ายภายใต้ GPL ดังนั้นคุณสามารถปรับใช้และใช้งานได้บนบริการของคุณ

ติดตั้ง TaskServer (taskd) บน CentOS 7

ติดตั้ง TaskServer (taskd) บน CentOS 7

ใช้ระบบที่แตกต่างกันอย่างไร TaskWarrior เป็นเครื่องมือจัดการเวลาแบบโอเพ่นซอร์สที่เป็นการปรับปรุงแอพพลิเคชั่น Todo.txt และโคลนของมัน เนื่องมาจาก

วิธีการติดตั้ง Selfoss RSS Reader บน CentOS 7 LAMP VPS

วิธีการติดตั้ง Selfoss RSS Reader บน CentOS 7 LAMP VPS

ใช้ระบบที่แตกต่างกันอย่างไร Selfoss RSS Reader เป็นฟรีและเปิดตัวเองบนเว็บโฮสต์อเนกประสงค์, สตรีมสด, ตอบโต้กับผู้ใช้ได้, ฟีดข่าว (RSS / Atom) reade

วิธีการติดตั้ง Kanboard บน CentOS 7

วิธีการติดตั้ง Kanboard บน CentOS 7

ใช้ระบบที่แตกต่างกันอย่างไร Kanboard เป็นซอฟต์แวร์ซอฟต์แวร์การจัดการโครงการโอเพ่นซอร์สฟรีที่ออกแบบมาเพื่ออำนวยความสะดวกและมองเห็นภาพการทำงานเป็นทีม

การตั้งค่าเซิร์ฟเวอร์ Half Life 2 บน CentOS 6

การตั้งค่าเซิร์ฟเวอร์ Half Life 2 บน CentOS 6

บทช่วยสอนนี้จะกล่าวถึงกระบวนการติดตั้งเซิร์ฟเวอร์เกม Half Life 2 บนระบบ CentOS 6 ขั้นตอนที่ 1: การติดตั้งข้อกำหนดเบื้องต้นเพื่อตั้งค่า ou

ไดรฟ์ที่แชร์ความพร้อมใช้งานสูงใช้ Vultr Block Storage และ GlusterFS

ไดรฟ์ที่แชร์ความพร้อมใช้งานสูงใช้ Vultr Block Storage และ GlusterFS

GlusterFS เป็นระบบไฟล์ที่เชื่อมต่อกับเครือข่ายซึ่งช่วยให้คุณแบ่งปันไดรฟ์สองตัวในอุปกรณ์หลายตัวบนเครือข่ายได้อย่างมีประสิทธิภาพ ระบบไฟล์นี้คือ

วิธีโยกย้ายกล่องจดหมายอย่างง่ายดายด้วย Imapsync บน CentOS 7

วิธีโยกย้ายกล่องจดหมายอย่างง่ายดายด้วย Imapsync บน CentOS 7

ใช้ระบบที่แตกต่างกันอย่างไร ในขณะที่การโยกย้ายเว็บไซต์มักจะไม่มีปัญหาบางครั้งก็ยากที่จะโยกย้ายกล่องอีเมล นี่คือ CAS โดยเฉพาะอย่างยิ่ง

วิธีการติดตั้ง PrestaShop บน CentOS 7

วิธีการติดตั้ง PrestaShop บน CentOS 7

PrestaShop เป็นโซลูชันอีคอมเมิร์ซแบบโอเพ่นซอร์สที่ได้รับความนิยม คุณสามารถใช้มันเพื่อสร้างร้านค้าออนไลน์ของคุณเองได้ฟรี ในบทช่วยสอนนี้ฉันจะแสดงให้คุณเห็นว่า

ReactOS: นี่คืออนาคตของ Windows หรือไม่?

ReactOS: นี่คืออนาคตของ Windows หรือไม่?

ReactOS ซึ่งเป็นโอเพ่นซอร์สและระบบปฏิบัติการฟรีพร้อมเวอร์ชันล่าสุดแล้ว สามารถตอบสนองความต้องการของผู้ใช้ Windows ยุคใหม่และล้ม Microsoft ได้หรือไม่? มาหาข้อมูลเพิ่มเติมเกี่ยวกับรูปแบบเก่านี้ แต่เป็นประสบการณ์ OS ที่ใหม่กว่ากัน

AI สามารถต่อสู้กับการโจมตีของแรนซัมแวร์ที่เพิ่มขึ้นได้หรือไม่

AI สามารถต่อสู้กับการโจมตีของแรนซัมแวร์ที่เพิ่มขึ้นได้หรือไม่

การโจมตีของ Ransomware กำลังเพิ่มขึ้น แต่ AI สามารถช่วยจัดการกับไวรัสคอมพิวเตอร์ตัวล่าสุดได้หรือไม่? AI คือคำตอบ? อ่านที่นี่รู้ว่า AI boone หรือ bane

เชื่อมต่อผ่าน WhatsApp Desktop App 24*7

เชื่อมต่อผ่าน WhatsApp Desktop App 24*7

ในที่สุด Whatsapp ก็เปิดตัวแอพเดสก์ท็อปสำหรับผู้ใช้ Mac และ Windows ตอนนี้คุณสามารถเข้าถึง Whatsapp จาก Windows หรือ Mac ได้อย่างง่ายดาย ใช้ได้กับ Windows 8+ และ Mac OS 10.9+

AI จะนำกระบวนการอัตโนมัติไปสู่อีกระดับได้อย่างไร

AI จะนำกระบวนการอัตโนมัติไปสู่อีกระดับได้อย่างไร

อ่านข้อมูลนี้เพื่อทราบว่าปัญญาประดิษฐ์กำลังได้รับความนิยมในหมู่บริษัทขนาดเล็กอย่างไร และเพิ่มโอกาสในการทำให้พวกเขาเติบโตและทำให้คู่แข่งได้เปรียบ

การอัปเดตเสริม macOS Catalina 10.15.4 ทำให้เกิดปัญหามากกว่าการแก้ปัญหา

การอัปเดตเสริม macOS Catalina 10.15.4 ทำให้เกิดปัญหามากกว่าการแก้ปัญหา

เมื่อเร็ว ๆ นี้ Apple เปิดตัว macOS Catalina 10.15.4 การอัปเดตเสริมเพื่อแก้ไขปัญหา แต่ดูเหมือนว่าการอัปเดตทำให้เกิดปัญหามากขึ้นที่นำไปสู่การสร้างเครื่อง Mac อ่านบทความนี้เพื่อเรียนรู้เพิ่มเติม

13 เครื่องมือดึงข้อมูลเชิงพาณิชย์ของ Big Data

13 เครื่องมือดึงข้อมูลเชิงพาณิชย์ของ Big Data

13 เครื่องมือดึงข้อมูลเชิงพาณิชย์ของ Big Data

ระบบไฟล์บันทึกคืออะไรและทำงานอย่างไร

ระบบไฟล์บันทึกคืออะไรและทำงานอย่างไร

คอมพิวเตอร์ของเราจัดเก็บข้อมูลทั้งหมดในลักษณะที่เรียกว่าระบบไฟล์บันทึก เป็นวิธีการที่มีประสิทธิภาพที่ช่วยให้คอมพิวเตอร์สามารถค้นหาและแสดงไฟล์ได้ทันทีที่คุณกดค้นหาhttps://wethegeek.com/?p=94116&preview=true

ภาวะเอกฐานทางเทคโนโลยี: อนาคตอันห่างไกลของอารยธรรมมนุษย์?

ภาวะเอกฐานทางเทคโนโลยี: อนาคตอันห่างไกลของอารยธรรมมนุษย์?

ในขณะที่วิทยาศาสตร์มีวิวัฒนาการไปอย่างรวดเร็ว โดยรับช่วงต่อความพยายามของเราอย่างมาก ความเสี่ยงในการทำให้ตัวเองตกอยู่ในภาวะภาวะเอกฐานที่อธิบายไม่ได้ก็เพิ่มขึ้นเช่นกัน อ่านว่าภาวะเอกฐานอาจมีความหมายสำหรับเราอย่างไร

ข้อมูลเชิงลึกเกี่ยวกับ 26 เทคนิคการวิเคราะห์ข้อมูลขนาดใหญ่: ตอนที่ 1

ข้อมูลเชิงลึกเกี่ยวกับ 26 เทคนิคการวิเคราะห์ข้อมูลขนาดใหญ่: ตอนที่ 1

ข้อมูลเชิงลึกเกี่ยวกับ 26 เทคนิคการวิเคราะห์ข้อมูลขนาดใหญ่: ตอนที่ 1

ผลกระทบของปัญญาประดิษฐ์ในการดูแลสุขภาพ 2021

ผลกระทบของปัญญาประดิษฐ์ในการดูแลสุขภาพ 2021

AI ในการดูแลสุขภาพได้ก้าวกระโดดอย่างมากจากทศวรรษที่ผ่านมา ดังนั้นอนาคตของ AI ในการดูแลสุขภาพจึงยังคงเติบโตทุกวัน