Nutanix NKP Authentication With LDAP

เตรียม nkp service user โดยเข้าไปที่เมนู Active Directory Users and Computers

Click Users เลือก New และ User

ตั้งชื่อ ตัวอย่างนี้ใช้ nkpsvc

หลังจากสร้าง user ใหม่แล้วเก็บ DN ไว้สำหรับใช้ในการ setup ใน NKP โดย click ที่ user เลือก Advanced Feature

click ที่ nkpsvc และเลือก Properties

click เลือก Attribute Editor และ copy ค่า distinguishedName สำหรับใช้ในการ config ที่ nkp

เปิดหน้า nkp-dashboard และเข้าไปที่เมนู Identity Providers

click Add Identity Provider และเลือก LDAP จากนั้นเลือก Workspace ที่ต้องการจะให้ Identity Provider นี้ถูกนำไปใช้ เลือก All Workspace หมายถึง Identity Provider นี้จะถูกใช้กับทุกๆ Workspace

หาค่า User Search Base DN โดย click ที่ Users เลือก Properties

ไปที่ Attribute Editor แล้วเลื่อนหา distinguishedName และทำการ copy ค่านี้เพื่อใช้สำหรับ User Search Base DN

ค่า User Search Username โดย click ที่ user nkpsvc เลือก Properties ไปที่ Attribute Editor แล้วเลื่อนไปที่ sAMAccountName

นำค่าที่ได้กรอกใน User Search Base DN และ User Search Username

กรอกค่าอื่นๆ ตามตัวอย่าง

จากนั้นกด save เพื่อบันทึก

ทำการสร้าง group เพื่อ authentication เข้ามายัง nkp platform จากนั้นสร้าง user และ assign ให้เข้ามาเป็น member ของ group ที่สร้างขึ้น

จากนั้นสร้าง Groups โดยเข้าไปที่เมนู Identity Providers และ click Add Identity Provider

ตั้งชื่อ group name และ group โดยต้องขึ้นต้นด้วย oidc: ตามด้วย group name ที่สร้างใน ldap

เข้าไปที่เมนู Access Control เพื่อให้ group NKP Admins มีสิทธิ์​เป็น Platform Admin ของระบบ NKP ที่สามารถเข้าถึงและจัดการ NKP Management Cluster และ NKP workload clusters ที่อยู่ในะรบบ

เลือก Cluster Role Bindings เลือก Add Roles ที่ group NKP Admins จากนั้น assign role Cluster Admin Role และ dkp-kommander-admin

Log out จากระบบ หน้า Log in จะมี option ให้เลือก login ได้มากกว่าหนึ่งช่องทาง ทดสอบ login ด้วย LDAP โดยเลือกที่ Log in with ntnxlab.local.AD

ตัวอย่างการสร้าง Role อื่นๆ เช่น

Workspace Admin มีสิทธิ์ Adminstrator สำหรับ NKP Workload Cluster โดยสามารถเข้าถึง NKP UI และเข้าถึง workspace ที่ถูก assign ให้เข้าถึงเท่านั้น โดยจะต้อง assign role “Workspace Admin Role” และ “Kommander Workspace Admin Role”

Project Deployer ที่มีสิทธิ์อยู่ภายใต้ namespace ของ NKP workload cluster และเข้าถึง kubernetes dashboad ได้ซึ่งตรงกับความต้องการพื้นฐานของทีม DevOps โดยจะต้อง assign role “App Deployer”

โครงสร้างการสร้าง NKP, Workspace และ Project

Nutanix NKP Installation

ขั้นตอนการติดตั้ง NKP ระบบจะสร้าง kubernetes ชั่วคราวสำหรับการติดตั้งเฉพาะ (bootstrap cluster) โดยจะ load package ที่จำเป็นคือ cluster-api ทำงานใน kubernetes ชั่วคราว อยู่ภายใต้ package ที่ชื่อว่า convoy โดย cluster-api จะสร้าง nkp management cluster ที่ infra platform ปลายทางจากข้อมูลที่ได้จาก NKP cli

cluster-api เป็น controller ที่ทำงานบน kubernetes ทำ infra auto provisioning ไปยัง platform ต่างๆ เนื่องจากการ provision kubernetes บน platform ที่แตกต่างกันจะต้องอาศัย api ที่แตกต่างกัน การใช้ kubernetes api จึงเป็นวิธีการที่ทำให้ไม่ว่า platform อะไรก็สามารถเรียกใช้ได้ด้วย api เดียวกัน cluster-api จึงเป็น standard ในการสร้าง kubernetes บน platform ที่แตกต่างกันได้ โดยมี vendor จากค่ายต่างๆ เข้าร่วมพัฒนาการเชื่อมต่อไปยัง platform ตัวเองจำนวนมาก เช่น nutanix, vmware, aws, google, azure เป็นต้น ทำให้ทำการสร้าง kubernetes เป็นเรื่องง่าย โดยไม่ต้องพัฒนาส่วนการเชื่อมต่อกับ platform ปลายทางเอง เพียงแค่ระบุรูปแบบ kubernetes cluster (yaml) จากนั้น cluster-api จะสร้าง kubernetes บน platform ปลายทางให้

การติดตั้ง Nutanix NKP จะต้องเตรียม docker และ kubectl ที่เครื่อง jumphost หรือเครื่องที่จะใช้ในการติดตั้ง ตัวอย่างนี้จะเป็นการติดตั้งโดยไม่ access internet และใช้ Rocky Linux

ตรวจสอบ docker ที่เครื่องที่ใช้ในการติดตั้ง สามารถทำได้ตามขั้นตอน Harbor Container Registry Installation

[nutanix@harbor nkp]$ docker version
Client: Docker Engine - Community
 Version:           28.3.0
 API version:       1.51
 Go version:        go1.24.4
 Git commit:        38b7060
 Built:             Tue Jun 24 15:45:22 2025
 OS/Arch:           linux/amd64
 Context:           default

Server: Docker Engine - Community
 Engine:
  Version:          28.3.0
  API version:      1.51 (minimum version 1.24)
  Go version:       go1.24.4
  Git commit:       265f709
  Built:            Tue Jun 24 15:43:38 2025
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.7.27
  GitCommit:        05044ec0a9a75232cad458027ca83437aae3f4da
 runc:
  Version:          1.2.5
  GitCommit:        v1.2.5-0-g59923ef
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

การติดตั้งจำเป็นต้องมี Container Registry ที่มี package bundle ของ nkp ขั้นตอนนี้ทำการทดสอบ login จากเครื่องที่ใช้ในการติดตั้ง

[nutanix@harbor nkp]$ docker login 10.38.252.79
Username: admin
Password:

WARNING! Your credentials are stored unencrypted in '/home/nutanix/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/

Login Succeeded

ติดตั้ง kubectl สำหรับเข้าถึง kubernetes

[nutanix@harbor nkp-v2.17.0]$ sudo curl -Lo /usr/local/bin/kubectl https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 53.7M  100 53.7M    0     0  74.2M      0 --:--:-- --:--:-- --:--:-- 74.3M
[nutanix@harbor nkp-v2.17.0]$ sudo chmod +x /usr/local/bin/kubectl

ติดตั้ง nkp cliโดย copy Download Link จาก nutanix portal จากหน้า download software

ขั้นตอนการติดตั้ง nkp cli

curl -fsSL https://raw.githubusercontent.com/nutanixdev/nkp-quickstart/main/get-nkp-cli | bash

#When prompted, enter the copy Downloadd Link

[nutanix@harbor ~]$ curl -fsSL https://raw.githubusercontent.com/nutanixdev/nkp-quickstart/main/get-nkp-cli | bash
open browser to site : https://portal.nutanix.com/page/downloads?product=nkp and find "NKP for Linux"
Enter 'NKP for Linux' download link: https://download.nutanix.com/downloads/nkp/v2.17.0/nkp_v2.17.0_linux_amd64.tar.gz?Expires=1768401776&Key-Pair-Id=APKAJTTNCWPEI42QKMSA&Signature=SiSx9R9vPquHatjI8NMUWCavIS1y~xYrzQHIIGd~ZBsphTBVk6HmB--Yqc82lPe2T5hUlBhFG~~jD75nNRYECvpKhumxqzZM9~WzqIDPxo16NDSX9eLokqe9dL9Oe8LBEDz-tC6BdMb0iOLv3nnxO-4sxyXg8pM0BHsvEat305nNAuZTQpO0d9DHxE2pF69FxCHxJ0KOebNOgArYiS63bl2tQHVAe0iWYtkLkm6rBvVNRlFSQokjCVw5u1aBoxpKSOMp4RAGo5iNHHf3hlwLL25yK7LI~glLKhMOD2KJ55Kkyc4pqfV053oHtmJurnGHkb87T36-7E1N3lNbx2AoAg__
NKP CLI installed successfully!
checking version
catalog: v0.8.1
diagnose: v0.12.0
imagebuilder: v2.17.0
kommander: v2.17.0
konvoy: v2.17.0
konvoybundlepusher: v2.17.0
mindthegap: v1.24.0
nkp: v2.17.0

Download NKP Airgapped Bundle สำหรับการติดตั้ง โดยการ copy Download Link จากหน้า nutanix portal

ขั้นตอนการ Download ผ่าน curl cli

[nutanix@harbor ~]$ curl -o nkp-air-gapped-bundle_v2.17.0_linux_amd64.tar.gz "https://download.nutanix.com/downloads/nkp/v2.17.0/nkp-air-gapped-bundle_v2.17.0_linux_amd64.tar.gz?Expires=1768402002&Key-Pair-Id=APKAJTTNCWPEI42QKMSA&Signature=DINg8wm1mGZR8fgXilavLmDe81UR126bHPdhLddcLuz8BQrXOPWSzHW29kVrNNUXP~CMS-cLArguoPGDwljnmBDaFACTsA9n~ooyA~Ff~9TEyjHiaWaNjez9gVawoyvHszti7Mfad7Bj4btFIsK9xGVYhJSuWAOryx2ieltb3GOEKrjjgZY4ykw7i3EzZrd9hXRga0DjbE3Lfy-YX~2h0~uhH~XiF08tvOI~LfTMi7AZDt2hJyZYgcXPqeVDJuFjureFdb4J4NNRu-lwbbrqipAQoMIYIOwUPLdV0oRFad4MAOUqqMhZIikSQSoYznkLb5WiFeVGxaagjcPFjflS1w__"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 20.8G  100 20.8G    0     0   135M      0  0:02:37  0:02:37 --:--:--  139M

ทำการ unzip file nkp-air-gapped-bunndle และทำการ load docker image เข้าไปยังระบบ docker ของเครื่อง จากนั้นทำการ upload image ไปยัง docker registry ที่เตรียมไว้ด้วย nkp cli

[nutanix@harbor ~]$ tar -xvf nkp-air-gapped-bundle_v2.17.0_linux_amd64.tar.gz

[nutanix@harbor nkp]$ cd nkp-v2.17.0/
[nutanix@harbor nkp-v2.17.0]$ docker load -i konvoy-bootstrap-image-v2.17.0.tar

[nutanix@harbor nkp-v2.17.0]$ docker image ls | grep konvoy-bootstrap
WARNING: This output is designed for human readability. For machine-readable output, please use --format.
mesosphere/konvoy-bootstrap:v2.17.0     9f13ef224cd1       5.86GB         2.92GB

[nutanix@harbor nkp-v2.17.0]$ nkp push bundle --bundle ./container-images/konvoy-image-bundle-v2.17.0.tar --to-registry=10.38.252.79/nkp --to-registry-username=admin --to-registry-password=Harbor12345 --to-registry-insecure-skip-tls-verify

[nutanix@harbor nkp-v2.17.0]$ nkp push bundle --bundle ./container-images/kommander-image-bundle-v2.17.0.tar --to-registry=10.38.252.79/nkp --to-registry-username=admin --to-registry-password=Harbor12345 --to-registry-insecure-skip-tls-verify

สร้าง ssh key สำหรับ access VM ที่สร้างขึ้นโดยระบบ

[nutanix@harbor ~]$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/nutanix/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/nutanix/.ssh/id_ed25519
Your public key has been saved in /home/nutanix/.ssh/id_ed25519.pub
The key fingerprint is:
SHA256://XGZ4k3rrFq2BC+QWmPk3NJNt972vQ5vHrnSuOyTm0 nutanix@harbor.local
The key's randomart image is:
+--[ED25519 256]--+
|                 |
|                 |
|          .      |
|         = +     |
|        S B + .  |
|         X + o . |
|          @ ..E.+|
|         o =.*o&X|
|          .o=*XX%|
+----[SHA256]-----+

ตัวอย่างนี้ใช้ ed25519 สำหรับการสร้าง key ซึ่งมีข้อดีดังนี้

Ed25519 offers several key advantages over RSA:

Performance: Ed25519 is significantly faster for both signing and verification operations. It uses elliptic curve cryptography which requires less computational overhead than RSA’s integer factorization approach.

Key size: Ed25519 uses 256-bit keys that provide security equivalent to 3072-bit RSA keys. This means much smaller key sizes for the same security level, reducing storage and transmission overhead.

Security design: Ed25519 was designed from the ground up to avoid many implementation pitfalls that have plagued RSA. It’s resistant to timing attacks, doesn’t require careful random number generation during signing (unlike RSA), and uses deterministic signatures.

Simplicity: The algorithm has fewer parameters and configuration options, reducing the chance of implementation errors. RSA requires choosing padding schemes, key sizes, and other parameters that can introduce vulnerabilities if done incorrectly.

Side-channel resistance: Ed25519 is designed to be resistant to side-channel attacks like timing and power analysis attacks, whereas RSA implementations often leak information through timing variations.

Future-proofing: While both are considered secure today, Ed25519’s elliptic curve foundation generally scales better as security requirements increase over time.

The main trade-off is that RSA is more widely supported in legacy systems, but for new applications, Ed25519 is generally the better choice due to its superior performance and security characteristics.

ติดตั้ง NKP ด้วย cli โดยจะต้อง export user และ password variable ก่อนจะ run nkp command

[nutanix@harbor nkp-v2.14.0]$ export NUTANIX_USER="admin"
export NUTANIX_PASSWORD='nx2Tech581!'

[nutanix@harbor ~]$ nkp create cluster nutanix --cluster-name nkp-mgmt \
--control-plane-prism-element-cluster PHX-POC252 \
--worker-prism-element-cluster PHX-POC252 \
--control-plane-subnets primary-PHX-POC252 \
--worker-subnets primary-PHX-POC252 \
--control-plane-endpoint-ip 10.38.252.10 \
--csi-storage-container default \
--endpoint https://10.38.252.7:9440 \
--control-plane-vm-image nkp-rocky-9.6-release-cis-1.34.1-20251206060914.qcow2 \
--worker-vm-image nkp-rocky-9.6-release-cis-1.34.1-20251206060914.qcow2 \
--kubernetes-service-load-balancer-ip-range 10.38.252.11-10.38.252.13 \
--registry-mirror-url https://10.38.252.79/nkp \
--registry-mirror-username admin \
--registry-mirror-password Harbor12345 \
--registry-mirror-cacert /home/nutanix/harbor/certs/harbor.local.crt \
--ssh-public-key-file /home/nutanix/id_ed25519.pub \
--ssh-username nutanix \
--airgapped \
--insecure \
--verbose 5 \
--timeout 0 \
--self-managed

กรณี airgap ต้องระบุ registry mirror เพื่อใช้ในการติดตั้ง ตามขั้นตอน upload konvoy และ kommander image ในขั้นตอนก่อนหน้า

ข้อมูล harbor.crt ได้มาจากขั้นตอนการสร้าง harbor หรือ สามารถ export ได้ด้วย cli

openssl s_client -connect 10.38.252.79:443 -showcerts </dev/null 2>/dev/null | openssl x509 -outform PEM > /home/nutanix/harbor.crt

กรณีที่การติดตั้งสามารถ access internet ได้ไม่จำเป็นต้องใช้ option –airgapped และระบบจะทำการติดตั้งโดยใช้ค่า default ถ้าไม่ระบุใน cli เช่น ขนาดของ VM และจำนวน VM เช่น Control plane จำนวน 3 VMs และ Worker จำนวน 4 VMs ดังตัวอย่าง options อื่นๆ ดังนี้

𝗘𝗡𝗩𝗜𝗥𝗢𝗡𝗠𝗘𝗡𝗧 𝗩𝗔𝗥𝗜𝗔𝗕𝗟𝗘𝗦
export CLUSTER_NAME="wskn-mgmt-ag" # Name of the Kubernetes cluster
export NUTANIX_PC_FQDN_ENDPOINT_WITH_PORT="https://10.168.100.4:9440" # Nutanix Prism Central endpoint URL with port
export CONTROL_PLANE_IP="10.168.102.30" # IP address for the Kubernetes control plane
export IMAGE_NAME="nkp-rocky-9.4-release-1.29.6-20240816215147" # Name of the VM image to use for cluster nodes
export PRISM_ELEMENT_CLUSTER_NAME="wskn-nongpu" # Name of the Nutanix Prism Element cluster
export SUBNET_NAME="non-gpu-airgap" # Name of the subnet to use for cluster nodes
export PROJECT_NAME="default" # Name of the Nutanix project
export CONTROL_PLANE_REPLICAS="3" # Number of control plane replicas
export CONTROL_PLANE_VCPUS="4" # Number of vCPUs for control plane nodes
export CONTROL_PLANE_CORES_PER_VCPU="1" # Number of cores per vCPU for control plane nodes
export CONTROL_PLANE_MEMORY_GIB="16" # Memory in GiB for control plane nodes
export WORKER_REPLICAS="3" # Number of worker node replicas
export WORKER_VCPUS="8" # Number of vCPUs for worker nodes
export WORKER_CORES_PER_VCPU="1" # Number of cores per vCPU for worker nodes
export WORKER_MEMORY_GIB="32" # Memory in GiB for worker nodes
export NUTANIX_STORAGE_CONTAINER_NAME="default-container-xxx" # Name of the Nutanix storage container
export CSI_FILESYSTEM="ext4" # Filesystem type for CSI volumes
export CSI_HYPERVISOR_ATTACHED="true" # Whether to use hypervisor-attached volumes for CSI
export LB_IP_RANGE="10.168.102.31-10.168.102.31" # IP range for load balancer services
export SSH_KEY_FILE="/root/.ssh/id_rsa.pub" # Path to the SSH public key file
export NUTANIX_USER="admin" # Nutanix PrismCentral username (left blank for security)
export NUTANIX_PASSWORD="" # Nutanix PrismCentral password (left blank for security)
export REGISTRY_URL="https://registry.wskn-ag.local/library" # URL for the private container registry
export REGISTRY_USERNAME="admin" # Username for authenticating with the private registry (left blank for security)
export REGISTRY_PASSWORD="" # Password for authenticating with the private registry (left blank for security)
export REGISTRY_CA="/root/wskn-ag-certs/server.crt" # Path to the CA certificate for the private registry

𝗜𝗡𝗦𝗧𝗔𝗟𝗟𝗔𝗧𝗜𝗢𝗡 𝗖𝗢𝗠𝗠𝗔𝗡𝗗
nkp create cluster nutanix --cluster-name $CLUSTER_NAME \
    --endpoint $NUTANIX_PC_FQDN_ENDPOINT_WITH_PORT\
    --control-plane-endpoint-ip $CONTROL_PLANE_IP \
    --control-plane-vm-image $IMAGE_NAME \
    --control-plane-prism-element-cluster $PRISM_ELEMENT_CLUSTER_NAME \
    --control-plane-subnets $SUBNET_NAME \
    --control-plane-pc-project $PROJECT_NAME \
    --control-plane-replicas $CONTROL_PLANE_REPLICAS \
    --control-plane-vcpus $CONTROL_PLANE_VCPUS \
    --control-plane-cores-per-vcpu $CONTROL_PLANE_CORES_PER_VCPU \
    --control-plane-memory $CONTROL_PLANE_MEMORY_GIB \
    --worker-vm-image $IMAGE_NAME \
    --worker-prism-element-cluster $PRISM_ELEMENT_CLUSTER_NAME \
    --worker-subnets $SUBNET_NAME \
    --worker-pc-project $PROJECT_NAME \
    --worker-replicas $WORKER_REPLICAS \
    --worker-vcpus $WORKER_VCPUS \
    --worker-cores-per-vcpu $WORKER_CORES_PER_VCPU \
    --worker-memory $WORKER_MEMORY_GIB \
    --ssh-public-key-file $SSH_KEY_FILE \
    --csi-storage-container $NUTANIX_STORAGE_CONTAINER_NAME \
    --csi-file-system $CSI_FILESYSTEM \
    --csi-hypervisor-attached-volumes=$CSI_HYPERVISOR_ATTACHED \
    --kubernetes-service-load-balancer-ip-range $LB_IP_RANGE \
    --insecure \
    --self-managed \
    --airgapped \
    --registry-mirror-url $REGISTRY_URL \
    --registry-mirror-cacert $REGISTRY_CA \
    --registry-mirror-username=$REGISTRY_USERNAME \
    --registry-mirror-password=$REGISTRY_PASSWORD

หลังจาก nkp cli ทำงาน ระบบจะสร้าง kubernetes ชั่วคราวโดยใช้ KIND (kubernetes in docker) โดย load package ที่ได้จาก konvoy-bootstrap-image ระบบจะสร้าง kubeconfig ตาม format ชื่อ cluster สามารถใช้ access KIND cluster เพื่อตรวจสอบสถานะการทำงานได้ดังนี้

[nutanix@harbor nkp-v2.17.0]$ export KUBECONFIG=nkp-mgmt-bootstrap.conf

ทำการ list logs ระหว่างการติดตั้งได้จาก container capx-controller-manager สำหรับ nutanix platform สำหรับ platform อื่นๆ สังเกตุจาก digit ที่ 4 คือ x = nutanix, a=aws, g=google, pp = preprovision, v=vmware, vcd=vmware cloud director, z=azure

[nutanix@harbor nkp-v2.17.0]$ kubectl logs -f capx-controller-manager-745948468d-dkjf5 -n capx-system

ตรวจสอบว่ามี container อะไรบ้างที่ถูกใช้ในการติดตั้ง

[nutanix@harbor nkp-v2.17.0]$ kubectl get pods -A -o yaml | grep image: | sort -h | uniq

รอจนกว่าระบบจะติดตั้งสมบูรณ์ โดยขั้นตอนการติดตั้งระบบจะลบ KIND และย้าย configuration ไปยัง cluster ปลายทาง โดยจะสร้าง kubeconfig ไว้ให้เพื่อ access ไปยัง cluster ที่สร้างขึ้นใหม่ ใช้เวลาประมาณ 10-20 นาที

Cluster default/nkp-mgmt kubeconfig was written to to the filesystem.
You can now view resources in the new cluster by using the --kubeconfig flag with kubectl.
For example: kubectl --kubeconfig="/home/nutanix/nkp-mgmt.conf" get nodes

Starting Kommander installation
 ✓ Deploying Flux
 ✓ Deploying Ingress certificate
 ✓ Creating kommander-overrides ConfigMap
 ✓ Deploying Git Operator
 ✓ Creating GitClaim for management GitRepository
 ✓ Creating GitClaimUser for accessing management GitRepository
 ✓ Deploying Flux configuration
 ✓ Deploying Kommander Operator
 ✓ Creating KommanderCore resource
 ✓ Cleaning up Kommander bootstrap resources
 ✓ Deploying Gatekeeper
 ✓ Creating PlatformVersionArtifact
 ✓ Deploying Kommander AppManagement
 ✓ 4 out of 14 core applications have been installed (waiting for dex, dex-k8s-authenticator and 8 more)
 ✓ 5 out of 14 core applications have been installed (waiting for dex, dex-k8s-authenticator and 7 more)
 ✓ 10 out of 14 core applications have been installed (waiting for dex-k8s-authenticator, kommander and 2 more)
 ✓ 11 out of 14 core applications have been installed (waiting for dex-k8s-authenticator, kommander-ui and 1 more)
 ✓ 13 out of 14 core applications have been installed (waiting for traefik-forward-auth-mgmt)

Cluster was created successfully! Get the dashboard details with:
nkp get dashboard --kubeconfig="/home/nutanix/nkp-mgmt.conf"

login ไปยัง nkp management platform โดยใช้ nkp cli เพื่อ generate user และ password รวมถึง dashboard url

[nutanix@harbor ~]$ nkp get dashboard --kubeconfig="/home/nutanix/nkp-mgmt.conf"
Username: compassionate_hellman
Password: CJey2OWLtc5nXwFXhDfDWC7tPsJlPu5gNiS2tKLl93J7avxCGvxYqKaPZ3zs3HJQ
URL: https://10.38.252.11/dkp/kommander/dashboard

Access dashboard ตามข้อมูลที่ได้

Harbor Container Registry Installation

Harbor เป็น container registry ที่ได้รับความนิยมมากในปัจจุบัน เนื่องจากมีความสามารถที่ช่วยให้เก็บ container image ไว้ภายในองค์กรแล้วยังมีความสามารถอื่นๆ เช่น การทำ proxy ไปยัง container registry ภายนอกเช่น docker hub เพื่อลดจำนวน request ไม่ให้ติดปัญหา request limit ของ docker hub การทำ replication ระหว่าง Harbor ด้วยกันกรณี DC/DR use case และ integrate กับ container scanning เช่น Trivy, Clair และ Notary สำหรับการทำ image signed เพื่อป้องกันการแก้ไขเปลี่ยนแปลง image

ในการติดตั้ง Harbor ต้องการ Docker และ Docker Compose ขั้นตอนการ install docker ขึ้นอยู่กับ OS โดยตัวอย่างนี้ติดตั้งบน Linux Rocky

#!/bin/bash
# Docker Installation Script for Rocky Linux
# 1. Update system packages
sudo dnf update -y
# 2. Install required packages
sudo dnf install -y dnf-utils device-mapper-persistent-data lvm2
# 3. Add Docker's official repository
sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 4. Install Docker Engine
sudo dnf install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 5. Start and enable Docker service
sudo systemctl start docker
sudo systemctl enable docker
# 6. Add current user to docker group (to run docker without sudo)
sudo groupadd docker
sudo usermod -aG docker $USER
sudo newgrp docker
# 7. Verify Docker installation
sudo docker --version
sudo docker run hello-world
# 8. Check Docker service status
sudo systemctl status docker
# 9. Optional: Install Docker Compose (if not using plugin version)
# sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
# sudo chmod +x /usr/local/bin/docker-compose
echo "Docker installation completed!"
echo "Please log out and log back in for group changes to take effect."
echo "Then you can run 'docker ps' without sudo."

กรณีที่ enable firewall จะต้องทำการ allow service docker ด้วย

# Open Docker ports if firewall is enabled
sudo firewall-cmd --permanent --add-service=docker
sudo firewall-cmd --reload

ทำการ download harbor installation binary และสร้างไฟล์ที่เกี่ยวข้อง

[nutanix@harbor harbor]$ HARBOR_VERSION=$(curl -s https://api.github.com/repos/goharbor/harbor/releases/latest | grep 'tag_name' | cut -d\" -f4)
[nutanix@harbor harbor]$ echo $HARBOR_VERSION
v2.13.1
[nutanix@harbor harbor]$ wget "https://github.com/goharbor/harbor/releases/download/${HARBOR_VERSION}/harbor-offline-installer-${HARBOR_VERSION}.tgz"
[nutanix@harbor harbor]$ tar xvf harbor-offline-installer-${HARBOR_VERSION}.tgz
[nutanix@harbor harbor]$ cd harbor
[nutanix@harbor harbor]$ cp harbor.yml.tmpl harbor.yml
[nutanix@harbor harbor]$ mkdir certs
[nutanix@harbor harbor]$ mkdir data
[nutanix@harbor harbor]$ mkdir generate-cert

ทำการ generate certificate สำหรับ Harbor ตัวอย่างนี้จะตั้ง host name เป็น harbor.local โดยเป็น self-signed certificate


# Generate CA Key
[nutanix@harbor harbor]$ cd generate-cert

# 1. Generate CA (Root Authority)
[nutanix@harbor generate-cert]$ openssl genrsa -out ca.key 4096

[nutanix@harbor generate-cert]$  openssl req -x509 -new -nodes -sha512 -days 3650 \
-subj "/C=TH/ST=BKK/L=BKK/O=ntnxlab/OU=demo/CN=ntnxlab-Internal-CA Root CA" \
-key ca.key -out ca.crt

# 2. Generate Server Key
[nutanix@harbor generate-cert]$  openssl genrsa -out harbor.local.key 2048

# 3. Generate CSR (Certificate Signing Request)
# Use the actual address you will type into your browser/CLI as the CN
[nutanix@harbor generate-cert]$  openssl req -sha512 -new \
-subj "/C=TH/ST=BKK/L=BKK/O=ntnxlab/OU=demo/CN=ntnxlab.local" \
-key harbor.local.key -out harbor.local.csr

# 4. Create v3.ext (Crucial fix: CA:FALSE and proper SAN)
[nutanix@harbor generate-cert]$  cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=ntnxlab.local
DNS.2=*.ntnxlab.local
DNS.3=harbor.ntnxlab.local
IP.1=10.38.252.79  # REPLACE with your actual Harbor VM IP
EOF

# 5. Generate Server Certificate (Signed by the CA)
[nutanix@harbor generate-cert]$  openssl x509 -req -sha512 -days 3650 \
-extfile v3.ext \
-CA ca.crt -CAkey ca.key -CAcreateserial \
-in harbor.local.csr \
-out harbor.local.crt

# verify new CA, expect correct subject output
[nutanix@harbor generate-cert]$  openssl x509 -in ca.crt -nameopt sep_multiline -subject -noout

# verify new CA, Should return OK
[nutanix@harbor generate-cert]$ openssl verify -CAfile ca.crt harbor.local.crt

# verify new CA, Should show your DNS and IP
[nutanix@harbor generate-cert]$ openssl x509 -in harbor.local.crt -text -noout | grep -A 1 "Subject Alternative Name"

To make your Kubernetes nodes or Docker clients trust this certificate, 
you must copy the ca.crt (not the harbor.local.crt) to the OS trust store:
RHEL/CentOS: Copy to /etc/pki/ca-trust/source/anchors/ and run update-ca-trust.
Ubuntu/Debian: Copy to /usr/local/share/ca-certificates/ and run update-ca-certificates.

Docker specific: Docker also requires the certs in
/etc/docker/certs.d/harbor.ntnxlab.local/ca.crt

# Optional - Convert the certificate to PEM format for docker
[nutanix@harbor generate-cert]$ openssl x509 -inform PEM -in harbor.local.crt -out harbor.local.cert

#copy harbor.local.crt and harbor.local.key for harbor server
[nutanix@harbor generate-cert]$ cp harbor.local.crt ../certs
[nutanix@harbor generate-cert]$ cp harbor.local.key ../certs

แก้ไขไฟล์ harbor.yml โดยมีค่าที่จำเป็นต้องแก้ดังนี้

hostname:
certificate:
private_keys:
data_volume:

hostname เป็น domain name ที่ map ไว้ที่ DNS server แต่ถ้าไม่มี DNS server สามารถใช้ IP แทนได้ดังตัวอย่างนี้

Certificate และ private_keys ได้จากขึ้นตอนสร้าง certificate ข้างต้น

data_volume คือข้อมูลระบบและ docker image ที่จัดเก็บใน harbor จำเป็นในการ backup กรณีระบบมีปัญหา และต้องการ recover

run install command เพื่อติดตั้ง harbor ทั้งนี้สามารถติดตั้ง components อื่นๆ ร่วมด้วยโดยใช้ options –with-trivy –with-notary –with-clair –with-chartmuseum

trivy และ clair สำหรับ vulnerability scanner และ notary สำหรับ container signing และ chartmuseum เพื่อให้ harbor สามารถเก็บ helm chart ได้ ตัวอย่างนี้จะติดตั้งเฉพาะ harbor

[nutanix@harbor harbor]$ sudo ./install.sh

หลังจากติดตั้งเสร็จ ทดสอบ login

[nutanix@harbor harbor]$ docker login 10.55.10.75
Username: admin
Password:
WARNING! Your credentials are stored unencrypted in '/home/nutanix/.docker/config.json'.
Configure a credential helper to remove this warning. See
https://docs.docker.com/go/credential-store/
Login Succeeded

กรณีที่ต้องการทำ registry proxy จะต้องไปสร้าง enpoint ที่ต้องการ connect ก่อน โดยเข้าไปที่เมนู Registries และ click +NEW ENDPOINT

กรณีนี้เลือก Docker Hub จากนั้นกรอกข้อมูล Access ID และ Access Secret เพื่อ connect ไปยัง Docker hub โดยต้องไปสร้าง access token ที่ Docker Hub ก่อน สามารถทำทดสอบการเชื่อมต่อโดย click TEST CONNECTION กด OK เพื่อเพิ่ม Endpoint

สร้าง Projects โดยเข้าไปที่เมนู Projects และ click + NEW PROJECT

กรอกข้อมูล Project name เลือก Access Level เลือก Proxy Cache และเลือก endpoint ที่สร้างในขั้นต้น และ click OK เพื่อสร้าง Project

สร้าง Projects อื่นๆ ตัวอย่างนี้สร้าง Project mirror สำหรับติดตั้ง NKP

กรอกข้อมูล Project

Project ที่สร้างขึ้น

BIAN – The Banking Industry Architecture Network

BIAN เป็นมาตรฐานกลางที่ธนาคารกำหนดขึ้นมาเพื่อให้เป็น common framework ของระบบธนาคาร โดยกำหนดคำกำจัดความของบริการ (service definition) ของระบบ Banking IT Services เพื่อการสื่อสารที่ตรงกัน ทำให้เกิดการทำงานร่วมกันระหว่างธนาคารได้ง่าย (Interoperability issue) รวมทั้งเป็นเป็น reference กลางของระบบธนาคาร และมาตรฐานการให้บริการด้วย APIs

BIAN นำเสนอโครงสร้างของการบริการธนาคารเป็นในรูปแบบลำดับชั้น ประกอบด้วย

Business Area กลุ่มของ Function งานต่างๆ ในระบบธนาคาร

Business Domain เป็นกลุ่มของส่วนงานภายใน Business Area

Service Domain เป็นส่วนของงานภายใน Business Domain เพื่อทำงานอย่างใดอย่างหนึ่งเช่น Service Domain ชื่อ SavingAccount ก็จะสื่อถืองานเกี่ยวกับ Service Account ที่ provide API เพื่อทำงานเกี่ยวกับ Saving Account

BIAN APIs ได้กำหนดข้อกำหนดมาตรฐานของ API โดยให้แบ่งเป็นแต่ละ Layer

Experience APIs เป็น APIs  สำหรับ user interact ซึ่งจะ specific สำหรับกลุ่มของการใช้งาน

Process APIs เป็น process ของแต่ละ APIs ที่อาจจะมีการเรียกใช้หลาย APIs เพื่อประมวลผลและแสดงผลลัพธ์ที่ต้องการ (Orchestrator)

System APIs เป็น APIs ตามข้อกำหนดของ BIAN และ BIAN Object Model ในการเข้าถึง System of Record (SOR) อื่นๆ เพื่อไม่ให้มีการเรียกใช้ Resource ได้โดยตรง ป้องกันไม่ให้เกิด dependency กับระบบรอบข้าง

ตัวอย่างการ Develop APIs ด้วย BIAN

ตัวอย่าง BIAN Architecture layer

ข้อมูลเพิ่มเติมอื่นๆ

BIAN Architecture

BIAN Service Landscape – Matrix view

BIAN Service Landscape – Value chain view

Semantic APIs Practitioner guide

Semantic APIs

C4 Architecture Model

C4 Model เป็นรูปแบบในการใช้ diagram เพื่ออธิบาย software architecture สำหรับสือสารภายในและภายนอกของทีม software development โดยแบ่งเป็นระดับตามจุดประสงค์ของการสื่อสารใน 4 ระดับ

System Context เป็น high-level ของระบบ software system ที่ให้บริการกับ User หรือ system ด้วยกันเอง และแสดงรายเอียดของ system อื่นๆ ที่เกี่ยวข้องด้วย (system dependency) มีการใช้ term อย่างเช่น application, product, service เป็นต้น scope ของ software system สามารถมองได้หลายมุม เช่น ในระดับ ทีม development, code repository หรือ กลุ่มของ application ที่ต้อง deployment ไปด้วยกัน

Container กลุ่มของ application และ data store ที่ประกอบอยู่ใน software system เพื่อให้ระบบทำงานได้ เช่น web application, mobile app, serverless function, database, file system, shell script เป็นต้น

Component กลุ่มของ function ที่เกี่ยวข้องภายใน Container ที่ประกอบกันเพื่อให้บริการกับภายนอก components อาจจะมีมากกว่าหนึ่ง component ในหนึ่ง container แต่ทั้งหมดจะมี deploy unit เดียวกัน หรือทำงานใน process เดียวกัน

Code เป็น implementation detail ของ component โดยแสดงในรูปแบบ UML class diagram, entity relationship diagram ปกติ code diagram จะถูก generate จาก development tool

K8S Sizing and Key Consideration

แนวทางเบื้องต้นเพื่อใช้ในการ Sizing ขนาดของ Kubernetes Cluster สำหรับ Application ใช้งานใน Kubernetes Environment สามารถใช้แนวทางดังนี้ในการพิจารณา

ต้องพิจารณาปัจจัยหลักๆ ประกอบด้วย 4 ปัจจัยคือ

Pods per node density

คือจำนวนของ Pod ซึ่งเป็น deployable unit (containers) ที่สามารถทำงานได้ต่อหนึ่งเครื่อง (Node) โดยเราต้องมีข้อมูล

  • vCPU ที่ pod ใช้งาน อาจจะใช้ cpu limit (ปกติจะต้องทำ cpu limit ไว้ เพื่อไม่ให้ pod ใช้ cpu ของเครื่องหมดจนส่งผลกระทบทั้ง cluster)
  • vCPU ของเครื่อง (Node) สำหรับใช้ในการ run pod
  • vCPU ทั้งหมดของเครื่อง (Node)
  • เปอร์เซ็นต์ของ cpu ที่จะ reserve ไว้สำหรับงานอื่นๆ เช่น system process

จากนั้นก็จะสามารถหาค่า pod per node density ได้จากการหาว่ามี vCPU สำหรับใช้ได้จริงเท่าไหร่ แล้ว หารด้วยค่าเฉลี่ยของ vCPU ที่ pod ใช้งาน เช่น

Node VM มี 8 vCPU และต้องการ reserve vCPU ไว้ 15% สำหรับ system process โดยค่าเฉลี่ยที่ pod ใช้งาน cpu core คือ 0.2 vCPU ต่อ Pod ก็จะหา pod per node density ได้ดังนี้

vCPU ที่ใช้งานได้ = 8 – (8*15/100) = 6.8 vCPU

Pod per node density = 6.8/0.2 = 34

** การกำหนดค่าเฉลี่ย vCPU ที่ pod ใช้งาน ต้องพิจารณา pods per CPU core จากคำแนะนำของ Kubernetes ที่ 1 CPU core จะสามารถรองรับได้ที่มากที่สุด 10 pods และจำนวน pod ต่อ Node ไม่ควรเกิน 110 pods – https://kubernetes.io/docs/setup/best-practices/cluster-large/

Master Node’s hardware config

ใช้ข้อมูลจาก kubernetes.io สำหรับเลือกขนาดของ Master Node

และต้องพิจารณา size ของเครื่องเพื่อรองรับ etcd คือ

ซึ่งถ้าต้องการ high availability จะต้องมีจำนวน node เป็นเลขคี่ตั้งแต่ 3 ขึ้นไป (Quorum)

ตัวอย่างเช่น ถ้าเรามี Worker node อยู่ 11 Node และต้อง support client จำนวน 500 client เราต้องใช้ Master node ด้วย spec 4vCPU memory 15 GBs

Number of Master Node in Cluster

เพื่อให้ระบบทำงานได้แม้จะมี Master node บางตัวไม่สามารถทำงานได้ ต้องพิจารณาจำนวนของ Master node ดังนี้

ตัวอย่างเช่น ถ้าต้องการให้ระบบยังคงทำงานได้ กรณีที่มี Master Node 2 ตัวเกิดปัญหา เราต้องเลือกจำนวน Master Node เป็น 5

High Availability and Fault Tolerance

ปัจจัยที่ต้องใช้ในการพิจารณามีดังนี้

  • จำนวน Node ที่มีปัญหา ณ​ เวลาใดเวลาหนึ่งพร้อมกัน
  • Node ที่ต้อง reserve ไว้ในกรณีที่มีการ update ระบบ
  • Pod per node density
  • จำนวน Node ที่เหลืออยู่หลังจาก Failure
  • จำนวน Capacity ที่เหลือสำหรับให้ Pod ทำงานได้หลังจาก Failure
  • จำนวน CPU core ที่เหลืออยู่หลังจาก Pod ทำงานเรียบร้อย หลังจาก Failure (rescheduling)

การหาจำนวน Node เช่น ถ้าเรามี 100 pods และต้องการให้ run 34 pods ต่อ node โดยสามารถ fail ได้ 2 Node ต่อเนื่อง และรองรับกรณี upgrade ระบบ ก็จะคำนวณ sizing ของ Node ได้คือ

100/34 + 2 + 1 = 6 worker node

การหา capacity ที่เหลือ และ pod per node density หลังจาก failure

เช่น มี pod จำนวน 100 pods ทำงานกระจายใน 6 node เมื่อมี 2 nodes ไม่สามารถให้บริการได้

จำนวน pod per node density เบื้องต้น = 100/6 = 16.6

จำนวน node ที่เหลืออยู่หลังจาก failure = 4 Node ซึ่งก็คือ resource หายไป 33% ของทั้งหมด

ทำให้ pod per node density เพิ่มขึ้นเป็น = 100/4 = 25

หลังจากได้ pods per node density แล้วต้องคำนวณด้วย cpu core ที่ pod ใช้งานถึงจะ sizing ขนาดของ node ได้ว่าจะต้องเผื่อ cpu และ memory ไว้ที่เท่าไหร่ถึงจะเหมาะสม

** Kubernetes support cluster auto scaling ได้ในกรณีที่ pod ไม่สามารถ scheduling ได้เนื่องจาก resource มีไม่เพียงพอ https://kubernetes.io/docs/concepts/cluster-administration/cluster-autoscaling/ แต่ก็จะมีช่วงเวลาที่ pod ไม่สามารถทำงานได้ในระหว่างที่มีการสร้าง node ใหม่เพื่อ join เข้ามาใน cluster

Workload Characteristic

เพื่อที่จะได้ค่า cpu และ memory ที่ pod ต้องการใช้จะต้องมีข้อมูลการทำงานจริงของ pod แล้วนำมาหาค่าเฉลี่ยเพราะแต่ละ pod ประกอบด้วย container ที่ application ถูกสร้างด้วย technology, architecture, algorithm ที่มี load หรือ usage แตกต่างกันในแต่ละช่วงเวลาการใช้งาน ตัวอย่าง memory ต่อ container ของแต่ละภาษา เช่น

  • Legacy JEE. 2Gb+ mem per container
  • SpringBoot 1Gb+ mem per container
  • NodeJS. 256Mb+ mem per container
  • Go 256Mb+ mem per container

Case Study

หา Sizing ของ Kubernetes Cluster เพื่อรองรับ 100 Springboot containers โดยมีข้อมูลดังนี้

  • Pod ทำงานโดยใช้ 0.2 vCPU และ Memory 0.4 GB
  • จำนวน pod per node density เท่ากับ 34
  • สามารถ fail ติดต่อกันได้ 2 ครั้ง
  • มี node ไว้ reserve สำหรับการ upgrade
  • ต้องมีการสำรอง resource ไว้ 15% สำหรับระบบ

Software Development Strategy

Software Development Team ต่างมี Process ในการ Develop Application ที่แตกต่างกันไปตามขนาดของทีม และความซับซ้อนของ Application แต่สิ่งหนึ่งที่เป็นมาตรฐานที่ใช้กันทั่วไปก็คือ Agile โดยมีการแบ่งงานออกมาเป็นงานย่อยๆ และทะยอย Deliver ทีละส่วน (Iteration) focus ปัญหาเฉพาะอย่าง ทำให้การพัฒนาทำได้ง่าย มีประสิทธิภาพ และคาดการณ์ในการส่งมอบได้แม่นยำกว่าการพัฒนาทั้งหมดให้เสร็จในทีเดียว (water-fall) จะว่าไปแล้วการนำหลัก Agile มาใช้ก็ควรจะส่งผลดีต่อทีมในการ Deliver Software แต่ก็ไม่ใช่ทุกทีมจะ Success เนื่องจากไม่มีประสบการณ์ และมองภาพแค่การแบ่งงานออกเป็นชิ้นย่อยๆ การนำ Agile มาใช้เป็นแค่ปลายทางของ Process เท่านั้น จำเป็นต้องมี Process อื่นร่วมด้วยเช่น Design Thinking และ Lean โดยสรุปได้ดังภาพ

กระบวนการ Design Thinking เป็นขั้นตอนที่ทำให้เราเข้าใจปัญหา โดย Focus ที่ทำไมถึงเกิดปัญหาขึ้น (WHY) ด้วยกระบวนการ Discovery จาก Group session กับผู้ที่เกี่ยวข้องทั้งหมด การพูดคุยกับ user (user interview) จาก code และวิเคราะห์จากข้อมูลต่างๆ ซึ่งผลลัพธ์ก็จะได้ปัญหาย่อยๆ หลายปัญหาก็เป็นได้ แต่ก็ต้องทำการ priority ว่า ปัญหาอะไรควรจะหยิบมาเข้ากระบวนการก่อนหลัง

หลังจากนั้นก็จะเข้ากระบวนการหาวิธีเพื่อที่จะแก้ปัญหาจากสมมุติฐานต่างๆ ด้วยการสร้างต้นแบบ (prototype) และประเมินผล รวมถึงปรับปรุง prototype เพื่อให้มั่นใจว่าเป็นทางเลือกที่ดีที่สุดในการแก้ปัญหานั้นๆ จนออกมาเป็น MVP (Minimum Viable Product) เพื่อนำเข้าสู่การพัฒนา เป็นกระบวนการ Lean Methodology (WHAT) ที่จะได้ Product ที่ถูกต้องสำหรับปัญหานั้นๆ (build the right thing)

หลังจากนั้นถ้ามีเรื่องอื่นๆ อีกก็ต้องกลับไปทำกระบวนการ Design Thinking สร้างสมมุติฐานและสร้าง Prototype วน Loop แบบนี้เรื่อยๆ เพื่อให้สามารถสร้าง Product backlog ในกระบวนการ Agile ได้

ขั้นตอนสุดท้ายถึงจะเป็น Agile คือการแบ่งงานออกมาเป็นส่วนย่อยๆ (Product backlog) ทำการ Develop และ Deliver เพื่อให้เสร็จแต่ละรอบภายใน 1-2 สัปดาห์ (Sprint) ถ้าใช้เวลามากกว่านี้ต้องทำการแบ่งงานให้ย่อยลงไปอีก ซึ่งประสิทธิภาพของการพัฒนาในแต่ละรอบ (Iteration) ขึ้นอยู่กับคุณภาพของ Product backlog และความซับซ้อนของแต่ละ Features เพื่อที่จะทำให้สามารถทำงานได้จริง และง่ายต่อการใช้ ซึ่งก็คือการสร้าง Software ด้วยวิธีการที่ถูกต้อง (build the thing the right way)

รายละเอียดของแต่ละช่วงเวลา และ Practice ที่ใช้

Ref: https://tanzu.vmware.com/agile

DevOps Framework

กระบวนการ Deliver Software จาก Ideas จนถึงใช้งานบน Production ต้องผ่าน process อะไรบ้างเมื่อพิจารณากระบวนการ DevOps เข้ามาเกี่ยวข้อง สามารถสรุปเป็นแนวทางได้ดังนี้

เราควรมี Product Team ที่ประกอบด้วยผู้ที่เกี่ยวของกับการพัฒนา Product เช่น Product Owner, Designer และ Developer ทั้งนี้ทีมควรพิจารณาเรื่อง Balance Team ที่ต้องมีผู้ที่เกี่ยวข้องกับการพัฒนาและส่งมอบ Product อยู่ในทีม เพื่อให้การดำเนินการใดๆ สามารถทำได้เลย ไม่ต้องเสียเวลาในการขอความร่วมมือใดๆ ข้าม Team เช่นการมี Security และ Operation อยู่ใน Team ด้วย จะทำให้ทุกคนเข้าใจใน Product ที่กำลังพัฒนา การตัดสินใจ การร่วมไม้ร่วมมือตั้งแต่ต้น และตลอดการพัฒนา โดยใช้หลักการ Why (ทำไมเราต้องพัฒนา) What (ส่ิงที่ต้องพัฒนาคืออะไร) How (จะพัฒนาขึ้นมาได้ยังไง) เพื่อส่งเสริมความเข้าใจ และทำงานร่วมกันภายในทีม

เครื่องมือที่เกี่ยวข้อง

  • Portfolio Management
  • Application Lifecycle Management
  • Team Collaboration and Work Tracking (Jira)
  • Security Architecture and Design
  • Threat Modeling
  • Knowledge Sharing (Confluence)

สิ่งที่เป็น Output ของ Team คือ Source Code รวมถึง Application Code, Testing Code และ Infra Code จะถูกจัดการด้วย Code Repository (GitLab, GitHub, GitBucket) เพื่อให้สามารถจัดการเรื่อง Versioning และการ Peer Review กับผู้ที่เกี่ยวข้องได้ และต้องมีการจัดการเรื่อง Quality ของ Code เช่น จำนวน Test Coverage การ Follow ตาม Practice ของการเขียน Code เช่น Code Quality/Secure Coding Standards (SonarQube, Snyk) และมีการ Integrate Security Tool เพื่อตรวจสอบช่องโหว่ด้านความปลอดภัยในระดับ Code เช่น Open Source Security & License Tracking (BlackDuck, Snyk), Static Application Security Testing – SAST (Coverity, Fortify, SonarQube, Checkmarx, Veracode) เป็นต้น

เมื่อ Code ผ่านกระบวนการตรวจสอบแล้ว กระบวนการต่อไปคือการ Build (maven, npm, MSBuild) โดยจะได้ Binary File ที่สามารถทำงานได้ (Working Software) ทั้งนี้ขั้นตอนการ Build จะมีการเรียก Unit Test (junit, Nunit) และ Functional Test (Cucumber) หลังจากนั้นก็จะจัดเก็บ Binary File ไว้ใน Application Repository (jFrog, Nexus)

ถ้า Software จะต้องทำงานบน Container Platform ก็ต้อง Pack Binary File ไว้ใน Container Format (Containerize) ด้วยเครื่องมือ Container Build (Docker file, Buildpack) และจัดเก็บไว้ใน Container Registry (Habor, jForg, DockerHub) หลังจากนั้นจึงจะทำการสร้าง SBOM (Software Bill of Material) เพื่อเป็น metadata file อธิบายถึง ข้อมูล Components ต่างๆ ที่ใช้ในการสร้าง Software ขึ้นมา แล้วต่อด้วย Software Composite Analysis – SCA (Trivy, BlackDuck, Snyk, jFrog X-Ray) เพื่อหาช่องโหว่ด้านความปลอดภัยของ software components ต่างๆ ที่นำมาใช้

จากนั้นจะต้องมีการออก Release Number ของ Software เพื่อเป็น Reference ในระบบ Release Management ที่ประกอบด้วย Features หรือ Update ต่างๆ ของ Software Release และ Update ไปยังระบบ Work Tracking และทำการ Tag Release Version ใน Code Repository

หลังจากกระบวนการออก Release Version ของ Software เสร็จจะขึ้นอยู่กับการตกลงของทีม Delivery และ QA ที่จะนำ Software Release เข้าสู่กระบวนการทดสอบโดยทีม QA และ Security ที่ครอบคลุมทั้งที่เป็น Functional และ Non-Function Test โดยมีเครื่องมือ Quality Management และ Update ไปยัง Work Tracking

เครื่องมือที่ QA ใช้ในการทดสอบ Software เช่น

  • Katalon Studio
  • Selenium
  • Appium
  • Applitools
  • Blazemeter
  • Saucelabs
  • Smartbear
  • Wiremock

เครื่องมือสำหรับ Dynamic Application Security Test เช่น

  • Fortify
  • Aqua Sec
  • OWASP ZAP
  • Tanable Web App Scan

เครื่องมือในการทำ performance test เช่น

  • JMeter
  • Smartbear
  • Postman
  • Locust

การจะนำ software ที่ผ่านการทดสอบแล้วขึ้น production อาจจะมีกระบวนการ approval process และทำการ deploy ด้วยวิธีการที่เหมาะสมเช่น blue-green, cannary  หรือ a/b testing หลังจากนั้นอาจจะมีเครื่องมือสำหรับตรวจสอบความปลอดภัย เช่น Infra Valnerabilities (Tenable Nessus), Interactive application security testing – IAST (AquaSec, Twistlock, Synopsys Seeker) และ Chaos Testing (Chaos Monkey, Chaos Mash) เพื่อให้มั่นใจว่าระบบจะสามารถทำงานได้ในสถานการณ์ต่างๆ เช่น ช่วง peak time และบางส่วนของระบบมีปัญหา

สิ่งที่สำคัญที่ขาดไม่ได้คือ log, monitoring และเก็บข้อมูลสถิติต่างๆ (Metric Collection – Prometheus, InfluxDB) เพื่อนำมาใช้ในการปรับปรุงระบบ ให้ดีขึ้นเรื่อยๆ ด้วยการ Update ข้อมูลกลับไปยัง Product Team พิจารณาแก้ไขให้ดีขึ้น

เครื่องมือสำหรับ Log และ Monitoring เช่น

  • Datadog
  • Grafana
  • Appdynamic
  • Dynatrace
  • Splunk
  • Solarwind
  • Elastic Stack (EFK, ELK)

Technology Adoption Lifecycle – Crossing the Chasm

Implement ระบบ IT ด้วยการนำ technology ใหม่ๆ เช่น containerize หรือพวก cloud native application รวมถึงหลักการใหม่ๆ อย่าง DevSecOps ที่บางองค์กรก็ success คือได้ผลลัพธ์จริง และสามารถ transform หน่วยงานและองค์กรด้วยการใช้ technology ใหม่ๆ ได้ แต่บางองค์กรก็ยังไม่ได้เห็นผลที่ชัดเจนและระบบส่วนใหญ่ก็ยังเป็นในรูปแบบเดิมอยู่นั้น สามารถอธิบายได้ด้วย Crossing the Chasm ซึ่งเป็นหนังสือที่เขียนโดย Geoffrey A. Moore ที่เมื่อมี technology ใหม่ องค์กรก็จะพยายามที่จะ adopt และนำมาใช้

ในช่วงที่เป็น Early adopters ทีมเริ่มพัฒนาและ integrate งานส่วนใหม่ๆ เข้าไปเพื่อให้แก้ปัญหา และช่วยงานต่างๆ ในการพัฒนาสินค้าและบริการให้ดียิ่งขึ้น เช่นอาจจะเรียกให้ vendors เข้ามา deliver application ให้เป็น container หรือให้ทีมต้องพัฒนา application ในรูป container ให้ใด้เร็วที่สุด เพื่อประเมินผลลัพธ์

แต่การที่เราจะเห็นการใช้ technology นี้ใน scale ที่ใหญ่ขึ้น และใช้งานต่อเนื่อง หรือไปต่อกับ technlogy นั้นอาจจะต้องใช้เวลา และเจออุปสรรคที่ค่อนข้างเยอะ (challenges) เพราะเรามักจะมองว่าการข้ามจาก early adopters ไป fast followers จะเป็น journey ที่ต่อเนื่องเช่น phase1 ไป phase2 แต่ความเป็นจริงแล้วมันคือการข้ามหุบเหว (chasm) ที่ถ้าเราข้ามไปไม่ได้เราก็จะยังคงอยู่ใน phase1 หรือ Early adopters ต่อไป หรือไม่ก็ยกเลิก technology นี้ไปเลย

การจะข้าม Chasm นี้ได้มักจะเกี่ยวกับเรื่องของ learning หลักการ fail fast และแก้ปัญหา challenge ต่างๆ ที่ต้องอาศัย practice และ foundation ของระบบ IT ที่เอื้ออำนวยต่อการ scale และปรับเปลี่ยนได้เร็ว จึงจะทำให้อยู่ใน Fast followers ได้ ซึ่งถือเป็นจุดที่องค์กรได้ประโยชน์สูงสุดในการนำ technology ดังกล่าวมาใช้

ทั้งนี้ Technology ใดๆ ล้วนมี life cycle ของตัวเอง พอเมื่อถึงช่วงเวลาหนึ่งก็จะไม่สามารถที่จะแก้ปัญหา หรือตอบสนองต่อเรื่องใหม่ๆ ได้ หรือไม่ก็หยุดพัฒนา ก็จะเกิด technology ใหม่เข้ามาทำให้ต้องกลับไป Early adopters อีกครั้ง แต่การตัดสินใจก็มักจะต้องมีเหตุมีผลที่เพียงพอเพราะการไม่อยากเปลี่ยนแปลงอะไร เนื่องจาก technology เดิมก็ยังใช้งานได้ถึงแม้จะมีบางอย่างที่มีปัญหาบ้างก็สามารถแก้ปัญหาด้วย work around บางอย่างได้ การเปลี่ยนแปลงใดๆ ก็ตามต้องการ proven ก่อนค่อนข้างเยอะ ก่อนที่จะยอมรับเพื่อเข้าสู่ Early adopters ซึ่งช่วงนี้เรียกว่า Conservatives

แต่ละองค์กรที่มีการ adopt technology ใดๆ ก็จะมีช่วงเวลาของ technlogy เสมอ แต่สิ่งสำคัญที่สุดคือการข้ามหุบเหว (chasm) ที่ต้องอาศัยทั้ง culture, process การร่วมไม้ร่วมมือ เพื่อให้สามารถข้ามอุปสรรค์ต่างๆ ไปได้

Principles of Software Design

สรุป design software principle สำหรับเป็น guidelines เพื่อใช้ในการ design software ซึ่งโดยทั่วไปแล้ว pattern และ practices ก็เหมือนเครื่องเมื่อ (tools) เพื่อที่จะทำให้สามารถสร้าง software ที่มีคุณภาพ ตัวอย่างเช่น

  • KISS – Keep it simple, stupid ใช้หลักการออกแบบที่ง่าย ไม่ซับซ้อน จะทำให้ software ทำงานได้ดีกว่า
  • DRY – Don’t repeat yourself หลีกเลี่ยงการทำอะไรซ้ำๆ หรือมีส่ิงเดียวกันหลายๆ ที่ ทำให้แก้ไขลำบาก
  • YAGNI – You aren’t gonna need it ไม่ควรพัฒนาหรือเพิ่ม function ใดๆ จนกว่าจะเห็นว่าจำเป็นจริงๆ
  • SoC – Separation of concerns หลักการออกแบบ software เป็นลักษณะ modular ที่ทำงานใดงานหนึ่งสมบูรณ์ในตัวเอง
  • SOLID – Single responsibility, Open/Close, Liskov substitution, Interface segregation, Dependency inversion เป็นหลักการในการเขียน object-oriented programming (OOP) ที่จะทำให้ software มีโครงสร้างที่ดี และแก้ไขได้ง่าย

Single Responsibility Principle – หลักการออกแบบ Class

หลักการที่เรามีแค่เหตุผลเดียวในการสร้าง class ขึ้นมาเพื่อทำงานใดงานหนึ่ง ไม่ควรให้ class ที่สร้างขึ้นมาทำงานหลายหน้าที่ (responsibility) เช่นออกแบบ class เพื่อหาพื้นที่รวมของรูปทรงต่างๆ ก็ไม่ควรให้ class นี้จะต้องทำเรื่องการแสดงผล (output format) ที่ได้ออกมาในรูป html หรือ json เพราะจะทำให้ class นี้ถูกสร้างขึ้นมาด้วยเหตุผลมากกว่าหนึ่งเหตุผล หรือถูกใช้หรือ support เฉพาะบางกลุ่มหรือบาง role

Open Closed Principle – หลักการออกแบบ Interface

Object หรือ entities ต้องสามารถ extend ได้ แต่ต้องแก้ไขไม่ได้ เป็นหลักการที่ทำให้โครงสร้างของ code เดิมไม่กระทบเมื่อมี type หรือ object ที่แตกต่างออกไป เช่น การที่เรามี class สำหรับรวมพื้นรวมของรูปทรงสี่เหลี่ยม กับวงกลม ด้วย method sum() ถ้าเรามีสามเหลี่ยมเพิ่มขึ้นมาก็จะหลีกเลี่ยงการแก้ไข method เดิมไม่ได้ เราสามารถแก้ไขได้ด้วยการสร้าง interface shape โดยให้ type object ใดๆ สามารถ extend ไปเพื่อ implement logic หา area ตัวเอง ก็จะทำให้ mothod sum() ของเราก็ไม่ต้องแก้ไขอะไร เพื่อที่จะ support รูปทรงใหม่ๆ

interface ShapeInterface
{
    public function area();
}
class Square implements ShapeInterface
{
    // ...
}
class Circle implements ShapeInterface
{
    // ...
} 
class AreaCalculator
{
    // ...
    public function sum()
    {
        foreach ($this->shapes as $shape) {
            if (is_a($shape, 'ShapeInterface')) {
                $area[] = $shape->area();
                continue;
            }
            throw new AreaCalculatorInvalidShapeException();
        }
        return array_sum($area);
    }
}

Liskov Substitution – หลักการออกแบบ Inheritance

เป็นหลักการที่ object ของ supper class จะต้องสามารถแทนทีด้วย object ของ subclass ได้โดยที่ต้องไม่ส่งผลต่อ program และ object ของ subclass จะต้องสามารถ access ทุก method และ property ของ super class

public interface Bird{
    public void fly();
    public void walk();
}

public class Parrot implements Bird{
    public void fly(){ // to do}
    public void walk(){ // to do }
}// ok 

public class Penguin implements Bird{
    public void fly(){ // to do }
    public void walk(){ // to do }
}  // it's break the principle of LSP. Penguin can not fly.

จากตัวอย่าง code จะเห็นว่า subclass สามารถ access superclass ได้ แต่จะเห็นว่า penguin ที่เป็น subclass เข้ากันไม่ได้กับ superclass เพราะ penguin ไม่สามารถบินได้จึงผิดหลัก Liskov substitution

public interface Bird{
    // to do;
}

public interface FlyingBird extends Bird{
    public void fly(){}
}

public interface WalkingBird extends Bird{
    public void work(){}
}

public class Parrot  implements FlyingBird, WalkingBird {
    public void fly(){ // to do}
    public void walk(){ // to do }
}

public class Penguin implements WalkingBird{
    public void walk(){ // to do }

ถ้าเปลี่ยนใหม่ให้ penguin สือทอดจาก walkingbird ก็จะทำให้ถูกต้องตามหลักการ และไม่ส่งผมต่อ program ทำให้เกิด bug

Interface segregation – หลักการออกแบบ Polymorphism

code จะต้องไม่ถูกบังคับให้ implement หรือเกี่ยวพันกับ method ที่ไม่ได้ใช้ เช่นกรณีที่เรามี class interface ที่มี method คำนวณพื้นที่ และปริมาตรสามมิติ ซึ่งถ้า type ของสี่เหลี่ยมเป็น 2 มิติก็จะไม่สามารถ implement method คำนวณปริมาตรได้เป็นต้น

Dependency Inversion – หลักการออกแบบ Decoupling and Abstraction

หลักการในการจัดการ dependency ของสอง object ที่เมื่อถ้าต้องเปลี่ยนไปใช้ อีก object จะทำได้ง่ายๆ โดยไม่กระทบกับ code ด้วยวิธีการใช้ intermediate object เพื่อเชื่มระหว่างทั้งสอง object เข้าด้วยกัน แทนที่จะให้ทั้งสอง object มีการเรียกใช้กันตรงๆ

public class Book {

    void seeReviews() {
         ...
    }

    void readSample() {
         ...
    }
}


public class Shelf {

     Book book;

     void addBook(Book book) {
          ...
     }

     void customizeShelf() {
          ...
     }
}

ตัวอย่างนี้ถ้าเราสร้าง shelf ไว้เก็บหนังสือ (book) อนาคตถ้าต้องการเก็บ DVD ด้วยก็เลี่ยงไม่ได้ที่ต้องแก้ class shelf เพราะความสัมพันธ์ที่ขั้นตรงต่อกันของทั้งสอง object

public interface Product {

    void seeReviews();

    void getSample();

}

public class Book implements Product {

    @Override
    public void seeReviews() { 
          ...
    }

    @Override
    public void getSample() {
          ...
    }
}

public class DVD implements Product {

    @Override
    public void seeReviews() { 
         ...
    }

    @Override  
    public void getSample() {
          ...
    }
}


public class Shelf {

    Product product;

    void addProduct(Product product) {
          ...
    }

    void customizeShelf() {
          ...
    }
}

ถ้าไม่ต้องการให้ object มี dependency ต่อกันก็ต้องสร้าง intermediate object ขึ้นมา ตัวอย่างนี้คือ object product ซึ่งเป็น abstraction ของทั้งสอง object ทำให้อนาคตถ้ามี object ใหม่ๆ เกิดขึ้น ก็สามารถเพิ่มเข้า หรือลบออกได้ง่าย

บทความที่น่าสนใจ และศึกษาเพิ่มเติมเพื่อให้เข้าใจมากขึ้นสำหรับ architecture และ software pattern อื่นๆ

Architecture

Design Patterns

Chaos Engineering