ื“ืขื•ื•ืขืœืึธืคึผื™ื ื’ ื–'ืื‘ื ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคึฟืึทืจ Kubernetes ื ื™ืฆืŸ Eclipse JKube

ืžื™ื˜ 25 ื™ืึธืจ ืฆื•ืจื™ืง, Java ืื™ื– ืืจื™ื™ืŸ ืื™ืŸ ื“ื™ ืžื™ื™ื ืกื˜ืจื™ื ืคื•ืŸ ืคึผืจืึธื’ืจืึทืžืžื™ื ื’ ืื•ืŸ ื™ื•ื•ืขื ื˜ืฉืึทื•ื•ืึทืœื™ ื’ืขื•ื•ืืจืŸ ืื™ื™ื ืขืจ ืคื•ืŸ ื“ื™ ื”ืึทืจืฅ ืขืœืขืžืขื ื˜ืŸ ืึทืจื•ื ื•ื•ืึธืก ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืกื˜ืึทืงืก ื–ืขื ืขืŸ ื’ืขื‘ื•ื™ื˜. ื”ื™ื™ึทื ื˜, ืึธื‘ืขืจ, ืคื™ืœืข ืžืขื ื˜ืฉืŸ ืื•ืŸ ืึธืจื’ืึทื ืึทื–ื™ื™ืฉืึทื ื– ื•ื•ืึธืก ื”ืึธื‘ืŸ ืฉื•ื™ืŸ ื’ืขื˜ืจื™ื™ึท ืฆื• Java ืคึฟืึทืจ ืคื™ืœืข ื™ืึธืจืŸ ื–ืขื ืขืŸ ืคืึทืจื ื•ืžืขืŸ ืžื™ื’ืจื™ื™ื˜ื™ื ื’ ืึธื“ืขืจ ื‘ืึทื˜ืจืึทื›ื˜ืŸ ืžื™ื’ืจื™ื™ื˜ื™ื ื’ ืฆื• ื“ืขืจ ืคึผืœืึทื˜ืคืึธืจืžืข. Kubernetes ืึธื“ืขืจ ื–ื™ื™ึทืŸ ื“ืขืจื™ื•ื•ืึทื˜ื™ื•ื•ื– ืึทื–ืึท ื•ื•ื™ RedHat OpenShift ืึธื“ืขืจ ืึทืžืึทื–ืึธืŸ ืขืงืก.

ื“ืขื•ื•ืขืœืึธืคึผื™ื ื’ ื–'ืื‘ื ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคึฟืึทืจ Kubernetes ื ื™ืฆืŸ Eclipse JKube

ืฆื•ื ื‘ืึทื“ื•ื™ืขืจืŸ, Kubernetes ื”ืื˜ ืึท ืึทืจืึธืคืึทื ื’ ืœืขืจื ืขืŸ ื•ื™ืกื‘ื™ื™ื’ ืื•ืŸ ื™ื ื˜ืจืึทื“ื•ืกื™ื– ืืŸ ืื ื“ืขืจ ืึทืคึผืขืจื™ื™ืฉืึทื ืึทืœ ืฉื™ื›ื˜ืข ืื™ืŸ ื“ืขืจ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ื•ื•ืึธืก Java ืคึผืจืึธื•ื’ืจืึทืžืขืจื– ื–ืขื ืขืŸ ืฆื•ื’ืขื•ื•ื•ื™ื ื˜ ืฆื•. ื”ื™ื™ึทื ื˜ ืžื™ืจ ื•ื•ืขื˜ ื–ืึธื’ืŸ ืื™ืจ ื•ื•ื™ ืฆื• ื ื•ืฆืŸ ืขืงืœื™ืคึผืกืข ื“ื–ืฉืงื•ื‘ืข, ืฆื• ืคืึทืจืคึผืึธืฉืขื˜ืขืจืŸ ื“ื™ ื ืึธืš ืึทืคึผืขืจื™ื™ืฉืึทื ื– ืคึฟืึทืจื‘ื•ื ื“ืŸ ืžื™ื˜ ืงื•ื‘ืขืจื ืขื˜ืขืก ืื•ืŸ ืงืึทื ื˜ื™ื™ื ืขืจื–, ืื•ืŸ ืขื ืฉื•ืจ ืึท ืคึผื™ื™ื ืœืึทืก ืžื™ื’ืจืึทื˜ื™ืึธืŸ ืฆื• ื“ื™ ื•ื•ืึธืœืงืŸ ืคึผืœืึทื˜ืคืึธืจืžืข ื‘ืฉืขืช ื”ืึทืœื˜ืŸ ื“ื™ ื‘ืึทืงืึทื ื˜ืข ื–'ืื‘ื ื™ืงืึธื•ืกื™ืกื˜ืึทื. ื“ืขืจืฆื•, ืžื™ืจ ื•ื•ืขืœืŸ ื•ื•ื™ื™ึทื–ืŸ ื•ื•ื™ ืฆื• ืฆืขื•ื•ื™ืงืœืขืŸ Java ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืื•ื™ืฃ ื“ื™ OpenShift ืคึผืœืึทื˜ืคืึธืจืžืข ื ื™ืฆืŸ ื“ื™ OpenShift Maven ืคึผืœื•ื’ื™ืŸ.

ื˜ืจืึทื“ื™ืฆื™ืึธื ืขืœ ื–'ืื‘ื ืื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก

ื˜ืจืึทื“ื™ืฆื™ืึธื ืขืœ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ื–'ืื‘ื (ืคื™ื’ื•ืจืข 1) ื™ื ื•ื•ืึทืœื•ื•ื– ื“ื™ ื“ืขื•ื•ืขืœืึธืคึผืขืจ ืฉืจื™ื™ื‘ืŸ ืงืึธื“, ืื•ืŸ ืงืจื™ื™ื™ื˜ื™ื ื’ ื“ื™ืคึผืœื•ื™ืžืึทื ื˜ ื•ื ื™ืฅ ืื™ืŸ ื“ื™ ืคืึธืจืขื ืคื•ืŸ JAR ืึธื“ืขืจ WAR ื˜ืขืงืขืก, ืื•ืŸ ื“ืึทืŸ ื“ื™ืคึผืœื•ื™ื™ื ื’ ืื•ืŸ ืœื•ื™ืคืŸ ื“ื™ ื˜ืขืงืขืก ืื•ื™ืฃ ืึท ื•ื•ืขื‘ ืึธื“ืขืจ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืกืขืจื•ื•ืขืจ. ื“ืขืจ ื”ื•ื™ืคึผื˜ ื•ื•ืขื’ ืฆื• ื˜ืึธืŸ ื“ืึธืก ืื™ื– ืฆื• ื ื•ืฆืŸ Maven ืคึฟื•ืŸ ื“ื™ ื‘ืึทืคึฟืขืœืŸ ืฉื•ืจื” ืึธื“ืขืจ ื ื•ืฆืŸ ืึท IDE ื•ื•ื™ IntelliJ ืึธื“ืขืจ Eclipse ืฆื• ืงืึธื“ ืื•ืŸ ืคึผืขืงืœ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื–. ื“ืขื•ื•ืขืœืึธืคึผืขืจืก ื–ืขื ืขืŸ ื’ืขื ื™ืฆื˜ ืฆื• ืžืึทื›ืŸ ืงืึธื“ ืขื ื“ืขืจื•ื ื’ืขืŸ ืื•ืŸ ื˜ืขืกื˜ื™ื ื’ ืึทืœืฅ ื•ื  ื“ื•ืจืš ืื™ื™ื“ืขืจ ืงืึทืžื™ื˜ื™ื ื’ ื“ื™ ืงืึธื“ ืื•ืŸ ืคืึธืจืœื™ื™ื’ืŸ ืขืก ืฆื• ื•ื•ืขืจืกื™ืข ืงืึธื ื˜ืจืึธืœ.

ื“ืขื•ื•ืขืœืึธืคึผื™ื ื’ ื–'ืื‘ื ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคึฟืึทืจ Kubernetes ื ื™ืฆืŸ Eclipse JKube

ืจื™ื™ืก. 1. ื˜ืจืึทื“ื™ืฆื™ืึธื ืขืœ ื–'ืื‘ื ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก.

Java ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ืคึฟืึทืจ ื“ื™ ืงืœืึธื•ื“

ื•ื•ืขืŸ ืžืึธื•ื•ื™ื ื’ ืฆื• ื•ื•ืึธืœืงืŸ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื–, Kubernetes ืื•ืŸ ืงืึทื ื˜ื™ื™ื ืขืจื–. ื“ืขืจื™ื‘ืขืจ, ื“ืขืจ ื“ืขื•ื•ืขืœืึธืคึผืขืจ ื“ืึทืจืฃ ืื™ืฆื˜ ืคึผืขืงืœ Java ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืื™ืŸ ืงืึทื ื˜ื™ื™ื ืขืจ ื‘ื™ืœื“ืขืจ ืื•ืŸ ืฉืึทืคึฟืŸ ืงื•ื‘ืขืจื ืขื˜ืขืก ืžืึทื ืึทืคืขืกื˜ื™ื– ืึทื– ื‘ืึทืฉืจื™ื™ึทื‘ืŸ ื“ื™ ื‘ื™ืœื“ืขืจ. ื“ื™ ืžืึทื ื™ืคืขืกืฅ ื–ืขื ืขืŸ ื“ืขืžืึธืœื˜ ื’ืขื•ื•ืขื ื“ื˜ ืฆื• ื“ืขืจ ืคึผืจืึธื“ื•ืงืฆื™ืข ืกืขืจื•ื•ืขืจ ืคืœื™ืกื ื“ื™ืง Kubernetes. ืื™ืŸ ืงืขืจ, Kubernetes ื ืขืžื˜ ื“ื™ ื‘ื™ืœื“ืขืจ ืคื•ืŸ ื“ื™ ืจืขื’ื™ืกื˜ืจื™ ืื•ืŸ ื“ื™ืคึผืœื•ื™ื“ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืœื•ื™ื˜ ื“ื™ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทื ื– ื•ื•ืึธืก ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขืฉืจื™ื‘ืŸ ืื™ืŸ ืžืึทื ื™ืคืขืกืฅ, ื•ื•ืึธืก ื–ืขื ืขืŸ ื™ื•ื–ืฉืึทื•ื•ืึทืœื™ ื™ืึทืžืœ ื˜ืขืงืขืก.

ื“ื™ ืžืขื˜ืึทืžืึธืจืคืึธืกื™ืก ืคื•ืŸ ื“ื™ ื‘ืขืงืึทื‘ืึธืœืขื“ื™ืง Java ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ืื™ืŸ ื“ื™ ื™ื‘ืขืจื’ืึทื ื’ ืฆื• ื“ื™ ื•ื•ืึธืœืงืŸ ืื™ื– ื’ืขื•ื•ื™ื–ืŸ ืื™ืŸ Fig. 2.

ื“ืขื•ื•ืขืœืึธืคึผื™ื ื’ ื–'ืื‘ื ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคึฟืึทืจ Kubernetes ื ื™ืฆืŸ Eclipse JKube

ืจื™ื™ืก. 2. ื–'ืื‘ื ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ืคึฟืึทืจ ื“ื™ ื•ื•ืึธืœืงืŸ.

ืขืงืœื™ืคึผืกืข ื“ื–ืฉืงื•ื‘ืข

ืžื™ื’ืจื™ื™ื˜ื™ื ื’ ืฆื• Kubernetes ืžื•ืกื™ืฃ ืืŸ ืื ื“ืขืจ ืึทืคึผืขืจื™ื™ืฉืึทื ืึทืœ ืฉื™ื›ื˜ืข ืฆื• ื“ื™ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก, ืื•ืŸ ืคื™ืœืข ื“ืขื•ื•ืขืœืึธืคึผืขืจืก ื–ืขื ืขืŸ ื ืขืจื•ื•ืขื– ื•ื•ืขื’ืŸ ื“ืขื ื•ื•ื™ื™ึทืœ ื–ื™ื™ ื•ื•ื™ืœืŸ ืฆื• ืคืึธืงื•ืก ืื•ื™ืฃ ื–ื™ื™ืขืจ ื”ืึทืจืฅ ืึทืจื‘ืขื˜ - ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืœืึธื’ื™ืง - ืืœื ื•ื•ื™ ื•ื•ื™ ืฆื• ืฆืขื•ื•ื™ืงืœืขืŸ ื–ื™ื™. ืื•ืŸ ื“ืึธืก ืื™ื– ื•ื•ื• ืขืก ืงื•ืžื˜ ืื™ืŸ ืฉืคึผื™ืœ. ืขืงืœื™ืคึผืกืข ื“ื–ืฉืงื•ื‘ืข, ื•ื•ืึธืก ืึทืœืึทื•ื– ื“ืขื•ื•ืขืœืึธืคึผืขืจืก ืฆื• ื ื•ืฆืŸ ื–ื™ื™ืขืจ ืœื™ื™ื‘ืจืขืจื™ื– ืื•ืŸ ืคึผืœื•ื’ื™ื ืก (JKube Kit ืฆื•ื–ืึทืžืขืŸ ืžื™ื˜ Kubernetes Maven ืคึผืœื•ื’ื™ืŸ ืึธื“ืขืจ OpenShift Maven ืคึผืœื•ื’ื™ืŸ) ืฆื• ืขืคืขืจื˜ืœืึทืกืœื™ ื“ื•ืจื›ืคื™ืจืŸ ืงืึทื ื˜ื™ื™ื ืขืจ ืื•ืŸ ืงื•ื‘ืขืจื ืขื˜ืขืก-ืคึฟืึทืจื‘ื•ื ื“ืขื ืข ืึทืคึผืขืจื™ื™ืฉืึทื ื– ื“ื•ืจืš ื ืึธื›ืคืึธืœื’ืŸ ื“ื™ ื“ื™ืึทื’ืจืึทืžืข ืื™ืŸ ืคื™ื’ื•ืจืข. 2.

ืื™ืŸ ื“ื™ ืจืขืฉื˜ ืคื•ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ืžื™ืจ ื•ื•ืขื˜ ื•ื•ื™ื™ึทื–ืŸ ืื™ืจ ื•ื•ื™ ืฆื• ืคืึทืจืคึผืึธืฉืขื˜ืขืจืŸ ื“ื™ Java ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ืื™ืŸ ื“ื™ Kubernetes ืกื•ื•ื™ื•ื•ืข ื“ื•ืจืš ื ื™ืฆืŸ Eclipse JKube ืžื™ื˜ ื“ื™ Kubernetes Maven ืคึผืœื•ื’ื™ืŸ.

ื•ื•ืึธืœืงืŸ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ื ื™ืฆืŸ Eclipse JKube

ื–ืืœ ืก ื‘ืึทื˜ืจืึทื›ื˜ืŸ ืึท ื‘ื™ืกืœ ืžืึทื“ืึทืคื™ื™ื“ ื–'ืื‘ื ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืกื›ืขืžืข ืคึฟืึทืจ ื“ื™ ื•ื•ืึธืœืงืŸ ืคึฟื•ืŸ ืคื™ื’. 2.

ื“ืขื•ื•ืขืœืึธืคึผื™ื ื’ ื–'ืื‘ื ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคึฟืึทืจ Kubernetes ื ื™ืฆืŸ Eclipse JKube

ืจื™ื™ืก. 3. ื–'ืื‘ื ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคึผืจืึธืฆืขืก ืคึฟืึทืจ ื“ื™ ื•ื•ืึธืœืงืŸ ื ื™ืฆืŸ ืขืงืœื™ืคึผืกืข ื“ื–ืฉืงื•ื‘ืข.

ื•ื•ื™ ืžื™ืจ ืงืขื ืขืŸ ื–ืขืŸ, ื“ืึธ ืึทืœืข ืึทืคึผืขืจื™ื™ืฉืึทื ื– ืคึฟืึทืจ ื™ื ื˜ืขืจืึทืงื˜ื™ื ื’ ืžื™ื˜ Kubernetes ืื•ืŸ ืงืึทื ื˜ื™ื™ื ืขืจื– (ื›ื™ื™ืœื™ื™ื˜ื™ื“ ืื™ืŸ ืจื•ื™ื˜ ืื™ืŸ ื“ื™ ื“ื™ืึทื’ืจืึทืžืข) ื–ืขื ืขืŸ ืจื™ืคึผืœื™ื™ืกื˜ ื“ื•ืจืš ืคืขืœื™ืงื™ื™ึทื˜ Eclipse JKube ืฆื™ืœ ื˜ืึทืกืงืก, ื•ื•ืึธืก ื–ืขื ืขืŸ ืœื™ืกื˜ืขื“ ืื™ืŸ ื˜ืึทื‘ืœืข. 1.

ื˜ื™ืฉ 1. ืขืงืœื™ืคึผืกืข ื“ื–ืฉืงื•ื‘ืข ืคืขืœื™ืงื™ื™ึทื˜ ื˜ืึทืกืงืก.

ืึทืจื‘ืขื˜
ื‘ื™ื ืข
ื‘ืึทืฉืจื™ื™ึทื‘ื•ื ื’

ืง8ืก: ื‘ื•ื™ืขืŸ
PRE_INTEGRATION_TEST
ื‘ื™ืœื“ื™ื ื’ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ

ืง8ืก: ืฉื˜ื•ืคึผืŸ
ื™ื ืกื˜ืึทืœื™ืจืŸ
ื•ืคึผืœืึธืึทื“ื™ื ื’ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ืขืจ ืฆื• ื“ื™ ืจืขื’ื™ืกื˜ืจื™

k8s: ืžื™ื˜ืœ
PROCESS_RESOURCES
ื“ื–ืฉืขื ืขืจื™ื™ื˜ื™ื ื’ K8s ืžืึทื ื™ืคืขืกืฅ

k8s: ืฆื•ืœื™ื™ื’ืŸ
ืฆื•ื ื•ื™ืคื ืขืžืขืŸ
ืึทืคึผืœื™ื™ื™ื ื’ ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ืžืึทื ื™ืคืขืกืฅ ืฆื• K8s

k8s: undeploy
UNDEPLOY
ืจื™ืžื•ื•ื•ื™ื ื’ K8s ืจืขืกื•ืจืกืŸ ื•ื•ืึธืก ื–ืขื ืขืŸ ื“ื™ืคึผืœื•ื™ื“ ืžื™ื˜ ืง8s: ืฆื•ืœื™ื™ื’ืŸ ืื•ืŸ ืง8ืก: ื“ื™ืคึผืœื•ื™

ื‘ืึทืžืขืจืงื•ื ื’: ืื•ื™ื‘ ืื™ืจ ื˜ืึธืŸ ื ื™ื˜ ื•ื•ืขืœืŸ ื˜ืึทืกืงืก ืฆื• ื ื•ืฆืŸ ื“ื™ ืึธื•ื ืขืจื– ื“ื™ืคืึธืœืฅ, ืื™ืจ ืงืขื ืขืŸ ืžืึทื ื™ื•ืึทืœื™ ืงืึทื ืคื™ื’ื™ืขืจ Eclipse JKube ืคึฟืึทืจ ื–ื™ืš, ื•ื•ื™ื™ึทืœ ืขืก ืฉื˜ื™ืฆื˜ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื“ื•ืจืš ืงืกืžืœ ะธ ืจืขืกื•ืจืกืŸ.

ืื™ืฆื˜ ืœืึธื–ืŸ ืื•ื ื“ื– ืงื•ืง ื‘ื™ื™ ื‘ื™ื™ืฉืคื™ืœืŸ ืคื•ืŸ ื ื™ืฆืŸ Eclipse JKube ืื•ืŸ Kubernetes Maven Plugin ื•ื•ืขืŸ ืื™ืจ ืึทืจื‘ืขื˜ ืžื™ื˜ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื–.

ื“ื™ืคึผืœื™ื™ื™ื ื’ ืึท Java ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืื•ื™ืฃ Kubernetes ื ื™ืฆืŸ Eclipse JKube

ืื™ืŸ ื“ืขื ื‘ื™ื™ึทืฉืคึผื™ืœ ืžื™ืจ ื•ื•ืขืœืŸ ืฆืขื•ื•ื™ืงืœืขืŸ ืึท ืคึผืฉื•ื˜ Java ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืื•ื™ืฃ ืึท ืงื ื•ื™ืœ ืžื™ื ื™ืงื•ื‘ืข ื ื™ืฆืŸ Eclipse JKube. ืžื™ื˜ ื“ื™ Kubernetes Maven ืคึผืœื•ื’ื™ืŸ, ืžื™ืจ ืงืขื ืขืŸ ืฉื˜ืขืœืŸ ื“ื™ืคึผืœื•ื™ืžืึทื ื˜ ืคึผืึทืจืึทืžืขื˜ืขืจืก ืึธืŸ ืฆื• ืฉืจื™ื™ึทื‘ืŸ ืงื™ื™ืŸ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ.

ื•ื•ื™ ืึท ื‘ื™ื™ึทืฉืคึผื™ืœ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืžื™ืจ ื ื•ืฆืŸ ืคึผืฉื•ื˜ ื˜ืจืึทืค - ื ื•ืžืขืจ ื’ืขื ืขืจืึทื˜ืึธืจ, ื•ื•ืึธืก ื˜ืจืื’ื˜ JSON ืจืขื–ื•ืœื˜ืึทื˜ ืื™ืŸ ื“ื™ / ื˜ืจืึทืค ืขื ื“ืคึผื•ื™ื ื˜:

~/work/repos/eclipse-jkube-demo-project : $ curl localhost:8080/random | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    45    0    45    0     0    818      0 --:--:-- --:--:-- --:--:--   818
{
  "id": "e80a4d10-c79b-4b9a-aaac-7c286cb37f3c"
}

ืฉืจื™ื˜ 1. ืืจืืคืงืืคื™ืข Kubernetes Maven ืคึผืœื•ื’ื™ืŸ

Kubernetes Maven ืคึผืœื•ื’ื™ืŸ ืื™ื– ืื™ืŸ ื“ื™ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™ ืžืึทื•ื•ืขืŸ ืกืขื ื˜ืจืึทืœ ืจื™ืคึผืึทื–ืึทื˜ืึธืจื™. ืฆื• ื ื•ืฆืŸ Eclipse JKube ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืœื™ื™ื’ืŸ ื“ื™ Kubernetes Maven ืคึผืœื•ื’ื™ืŸ ืฆื• ื“ื™ื™ืŸ pom.xml ื•ื•ื™ ืึท ื“ืขืคึผืขื ื“ืขื ืกื™:

<plugin>
     <groupId>org.eclipse.jkube</groupId>
     <artifactId>kubernetes-maven-plugin</artifactId>
     <version>${jkube.version}</version>
 </plugin>

ืื•ื™ื‘ OpenShift ืื™ื– ื’ืขื ื™ืฆื˜ ืึทื ืฉื˜ืึธื˜ ืคื•ืŸ ืจื™ื™ืŸ Kubernetes, ืคึผืึธm.xml ืื™ื– ืžืึทื“ืึทืคื™ื™ื“ ื•ื•ื™ ื’ื™ื™ื˜:

<plugin>
     <groupId>org.eclipse.jkube</groupId>
     <artifactId>openshift-maven-plugin</artifactId>
     <version>${jkube.version}</version>
 </plugin>

ืฉืจื™ื˜ 2. ื‘ื•ื™ืขืŸ ื“ื™ ื“ืึธืงืงืขืจ ื‘ื™ืœื“

ื“ื™ JAR ื˜ืขืงืข ืคื•ืŸ โ€‹โ€‹ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื‘ื•ื™ื˜ ืžื™ื˜ ื“ื™ mvn ืคึผืขืงืœ ื‘ืึทืคึฟืขืœ, ืื•ืŸ ื“ื™ mvn ืฆื™ืœ ืึทืจื‘ืขื˜ k8s:build ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื™ื ื˜ ืฆื• ื‘ื•ื™ืขืŸ ืึท ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืคื•ืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ. ื‘ืึทืžืขืจืงื•ื ื’ ืึทื– ืžื™ืจ ื”ืึธื‘ืŸ ืึธื•ื•ื•ืขืจืจื™ื™ื“ ื“ื™ ืคืขืœื™ืงื™ื™ึทื˜ ื‘ื™ืœื“ ื ืึธืžืขืŸ ืžื™ื˜ ื“ืขื ืคืึทืจืžืึธื’:

<jkube.generator.name>docker.io/rohankanojia/random-generator:${project.version}</jkube.generator.name>

ืื™ื™ื“ืขืจ ืื™ืจ ื‘ื•ื™ืขืŸ ื“ืขื ื‘ื™ืœื“, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืžืึทื›ืŸ ื–ื™ื›ืขืจ ืึทื– ื“ื™ ื“ืึธืงืงืขืจ ื“ื™ื™ืžืึทืŸ ืื™ื– ื™ืงืกืคึผืึธื•ื–ื“ ืจื™ื›ื˜ื™ืง. ื“ืึธืก ืงืขืŸ ื–ื™ื™ืŸ ื’ืขื˜ืืŸ ืžื™ื˜ ื“ื™ ืคืืœื’ืขื ื“ืข ื‘ืึทืคึฟืขืœ:

$ eval $(minikube docker-env)

ื“ืขืจื ืึธืš ืžื™ืจ ืึทืจื™ื™ึทืŸ ื“ื™ mvn k8s:build ื‘ืึทืคึฟืขืœ, ืื•ืŸ ื“ืึธืก ืื™ื– ื•ื•ืึธืก ืžื™ืจ ื•ื•ืขืœืŸ ื–ืขืŸ ืื•ื™ืฃ ื“ืขื ืขืงืจืึทืŸ ื•ื•ืขืŸ ืžื™ืจ ื‘ื•ื™ืขืŸ ื“ื™ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ ื“ื™ Eclipse JKube ื‘ื•ื™ืขืŸ ืึทืจื‘ืขื˜:

~/work/repos/eclipse-jkube-demo-project : $ mvn k8s:build
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- kubernetes-maven-plugin:1.0.0-rc-1:build (default-cli) @ random-generator ---
[INFO] k8s: Running in Kubernetes mode
[INFO] k8s: Building Docker image in Kubernetes mode
[INFO] k8s: Running generator spring-boot
[INFO] k8s: spring-boot: Using Docker image quay.io/jkube/jkube-java-binary-s2i:0.0.7 as base / builder
[INFO] k8s: [docker.io/rohankanojia/random-generator:0.0.1] "spring-boot": Created docker-build.tar in 251 milliseconds
[INFO] k8s: [docker.io/rohankanojia/random-generator:0.0.1] "spring-boot": Built image sha256:a20e5
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  5.053 s
[INFO] Finished at: 2020-08-10T11:28:23+05:30
[INFO] ------------------------------------------------------------------------
~/work/repos/eclipse-jkube-demo-project : $

ืฉืจื™ื˜ 3. ื•ืคึผืœืึธืึทื“ ื“ื™ ื‘ื™ืœื“ ืฆื• ื“ื™ ื“ืึธืงืงืขืจ ืจืขื’ื™ืกื˜ืจื™

ื ืึธืš ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขื‘ื•ื™ื˜ ื“ื™ ื“ืึธืงืงืขืจ ื‘ื™ืœื“ ืžื™ื˜ ื“ื™ ืฉื˜ื•ืคึผืŸ ืจืขื’ื™ืกื˜ืจื™ ืงืึทื ืคื™ื’ื™ืขืจื“ (ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคืึทืœ ืขืก ืื™ื– docker.io), ืžื™ืจ ืงืขื ืขืŸ ืฉื™ืงืŸ ื“ืขื ื‘ื™ืœื“ ืฆื• ื“ื™ ืจืขื’ื™ืกื˜ืจื™. ื“ืึธืก ืื™ื– ื•ื•ืึธืก ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื–ืŸ ื ืึธืš ืžื™ืจ ื‘ืขื˜ืŸ Eclipse JKube ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ื“ื™ mvn k8s: ืคึผื•ืฉ ืฉื˜ื•ืคึผืŸ ืึทืจื‘ืขื˜:

~/work/repos/eclipse-jkube-demo-project : $ mvn k8s:push
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- kubernetes-maven-plugin:1.0.0-rc-1:push (default-cli) @ random-generator ---
[INFO] k8s: Running in Kubernetes mode
[INFO] k8s: Building Docker image in Kubernetes mode
[INFO] k8s: Running generator spring-boot
[INFO] k8s: spring-boot: Using Docker image quay.io/jkube/jkube-java-binary-s2i:0.0.7 as base / builder
[INFO] k8s: The push refers to repository [docker.io/rohankanojia/random-generator]
5dcd9556710f: Layer already exists 
b7139ad07aa8: Layer already exists 
b6f081e4b2b6: Layer already exists 
d8e1f35641ac: Layer already exists 
[INFO] k8s: 0.0.1: digest: sha256:9f9eda2a13b8cab1d2c9e474248500145fc09e2922fe3735692f9bda4c76002d size: 1162
[INFO] k8s: Pushed docker.io/rohankanojia/random-generator:0.0.1 in 7 seconds 
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  11.222 s
[INFO] Finished at: 2020-08-10T11:35:37+05:30
[INFO] ------------------------------------------------------------------------
~/work/repos/eclipse-jkube-demo-project : $ 

ื ืึธืš ืฉื™ืงืŸ ื“ื™ ื‘ื™ืœื“, ืื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืงืึธื ื˜ืจืึธืœื™ืจืŸ ืึทื– ืขืก ืื™ื– ืึทืจื™ื™ึทื ื’ืขืจืขื›ื ื˜ ืื™ืŸ ื“ื™ ืจืขื’ื™ืกื˜ืจื™. ืื™ืŸ ืื•ื ื“ื–ืขืจ ืคืึทืœ, ืžื™ืจ ืคืฉื•ื˜ ื–ืขืŸ ืขืก ืื™ืŸ Docker Hub, ื•ื•ื™ ื’ืขื•ื•ื™ื–ืŸ ืื™ืŸ Fig. 4.

ื“ืขื•ื•ืขืœืึธืคึผื™ื ื’ ื–'ืื‘ื ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคึฟืึทืจ Kubernetes ื ื™ืฆืŸ Eclipse JKube

ืจื™ื™ืก. 4. ื“ื™ ื‘ื™ืœื“ ื’ืขืฉื™ืงื˜ ืฆื• ื“ื™ ืจืขื’ื™ืกื˜ืจื™ ืืจื•ื™ืก ืื™ืŸ Docker Hub.

ืฉืจื™ื˜ 4. ื’ืขื ืขืจืึทื˜ืข ืงื•ื‘ืขืจื ืขื˜ืขืก ืžื™ื˜ืœ ืžืึทื ืึทืคืขืกืฅ ืคึฟืึทืจ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ

ืึทื–ื•ื™, ืžื™ืจ ื”ืึธื‘ืŸ ื’ืขื–ืืžืœื˜ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ื‘ื™ืœื“, ืื™ืฆื˜ ืžื™ืจ ื“ืึทืจืคึฟืŸ ืฆื• ืฉืจื™ื™ึทื‘ืŸ Kubernetes ืžืึทื ื™ืคืขืกืฅ. ืฆื• ื˜ืึธืŸ ื“ืึธืก, Eclipse JKube ื”ืื˜ ืึท ืึทืจื‘ืขื˜ ื•ื•ืึธืก ื“ื–ืฉืขื ืขืจื™ื™ืฅ ืฉื˜ืจืขื ื’ ืจื™ืกืึธืจืกื™ื– ื‘ืื–ื™ืจื˜ ืื•ื™ืฃ ื“ื™ ืึทื ื“ืขืจืœื™ื™ื™ื ื’ Java ืคืจื™ื™ืžื•ื•ืขืจืง (ืคืจื™ืœื™ื ื’ ืฉื˜ื™ื•ื•ืœ, ืงื•ื•ืึทืจืงื•ืก, Vert.x ืึธื“ืขืจ ืขื˜ืœืขื›ืข ืื ื“ืขืจืข). ืื™ืจ ืงืขื ื˜ ืื•ื™ืš ืงืึทืกื˜ืึทืžื™ื™ื– ื“ื™ ืžืึทื ืึทืคืขืกื˜ื™ื™ืฉืึทืŸ ื“ื•ืจืš ื ื™ืฆืŸ ืึท ืงืกืžืœ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื˜ืขืงืข ืื•ืŸ ืคึผืœื™ื™ืกื™ื ื’ ืจื•ื™ ืคืจืึทื’ืžืึทื ืฅ (ืคืจืึทื’ืžืึทื ืฅ ืคื•ืŸ ื“ื™ ืคืืจืœืื ื’ื˜ ืžื™ื˜ืœ ื‘ืึทืฉื™ื™ึทืžืคึผืขืจืœืขืš) ืื™ืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ื˜ืขืงืข src/main/jkube. ืื™ืŸ ื“ืขื ืคืึทืœ, ื“ื™ื™ืŸ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ ื•ื•ืขื˜ ื–ื™ื™ืŸ ื•ืคึผืœืึธืึทื“ืขื“ ืฆื• ื“ื™ ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ืžืึทื ื™ืคืขืกืฅ.

ืื™ืŸ ืื•ื ื“ื–ืขืจ ื‘ื™ื™ึทืฉืคึผื™ืœ, ืžื™ืจ ืœืึธื–ืŸ ืึทืœืฅ ื•ื•ื™ ืื™ื–, ืื•ืŸ ื“ืขืจื™ื‘ืขืจ Eclipse JKube ื“ื–ืฉืขื ืขืจื™ื™ืฅ ืึท ื‘ืึทืฉื™ื™ึทืžืคึผืขืจืœืขืš ืคึฟืึทืจ ื“ื™ ืคืขืœื™ืงื™ื™ึทื˜ ื“ื™ืคึผืœื•ื™ืžืึทื ื˜ ืื•ืŸ ืคึฟืึทืจ ื“ื™ ืกืขืจื•ื•ื™ืก ืžื™ื˜ ื˜ื™ืคึผ ClusterIP. ืื•ืŸ ื‘ืœื•ื™ื– ื“ืขืžืึธืœื˜ ืžื™ืจ ืžืึธื“ื™ืคื™ืฆื™ืจืŸ ื“ื™ ืกืขืจื•ื•ื™ืก ืžืึทื ืึทืคืขืกื˜ื™ื™ืฉืึทืŸ ืฆื• ื˜ื•ื™ืฉืŸ ื“ื™ ื“ื™ื ืกื˜ ื˜ื™ืคึผ ืฆื• NodePort. ืื™ืจ ืงืขื ืขืŸ ืึธื•ื•ื•ืขืจืจื™ื™ื“ ื“ื™ ืคืขืœื™ืงื™ื™ึทื˜ ื ืึทื˜ื•ืจ ื ื™ืฆืŸ ื“ื™ ืคืืœื’ืขื ื“ืข ืคืึทืจืžืึธื’:

<jkube.enricher.jkube-service.type>NodePort</jkube.enricher.jkube-service.type>

ื“ืึธืก ืื™ื– ื•ื•ื™ ื“ื™ ืคืึทืจืฉื˜ืขืœืŸ ืจืขื–ื•ืœื˜ืึทื˜ ืงื•ืงื˜ ื•ื•ื™ ื ืึธืš ืžื™ืจ ื‘ืขื˜ืŸ Eclipse JKube ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ื“ื™ mvn k8s: ืžื™ื˜ืœ ืจื™ืกืึธืจืก ืึทืจื‘ืขื˜.

~/work/repos/eclipse-jkube-demo-project : $ mvn k8s:resource
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- kubernetes-maven-plugin:1.0.0-rc-1:resource (default-cli) @ random-generator ---
[INFO] k8s: Running generator spring-boot
[INFO] k8s: spring-boot: Using Docker image quay.io/jkube/jkube-java-binary-s2i:0.0.7 as base / builder
[INFO] k8s: jkube-controller: Adding a default Deployment
[INFO] k8s: jkube-service: Adding a default service 'random-generator' with ports [8080]
[INFO] k8s: jkube-healthcheck-spring-boot: Adding readiness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 10 seconds
[INFO] k8s: jkube-healthcheck-spring-boot: Adding liveness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 180 seconds
[INFO] k8s: jkube-revision-history: Adding revision history limit to 2
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.344 s
[INFO] Finished at: 2020-08-10T11:38:11+05:30
[INFO] ------------------------------------------------------------------------
~/work/repos/eclipse-jkube-demo-project : $ ls target/classes/META-INF/jkube/kubernetes
random-generator-deployment.yml  random-generator-service.yml
~/work/repos/eclipse-jkube-demo-project : $ cat target/classes/META-INF/jkube/kubernetes/random-generator-deployment.yml | head -n10
---
apiVersion: apps/v1
kind: Deployment
metadata:
  annotations:
    jkube.io/git-url: [email protected]:rohanKanojia/eclipse-jkube-demo-project.git
    jkube.io/git-commit: 1ef9ef2ef7a6fcbf8eb64c293f26f9c42d026512
    jkube.io/git-branch: master
    jkube.io/scm-url: https://github.com/spring-projects/spring-boot/spring-boot-starter-parent/random-generator
    jkube.io/scm-tag: HEAD
~/work/repos/eclipse-jkube-demo-project : $

ืฉืจื™ื˜ 5. ืฆืขื•ื•ื™ืงืœืขืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืฆื• ื“ื™ Kubernetes ืงื ื•ื™ืœ

ืื™ืฆื˜ ืžื™ืจ ื–ืขื ืขืŸ ืึทืœืข ื’ืจื™ื™ื˜ ืฆื• ืฆืขื•ื•ื™ืงืœืขืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ: ืžื™ืจ ื”ืึธื‘ืŸ ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ื–ื™ื™ืŸ ื‘ื™ืœื“ ืื•ืŸ ื“ืึทืŸ ืื•ื™ื˜ืึธืžืึทื˜ื™ืฉ ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ืžื™ื˜ืœ ืžืึทื ื™ืคืขืกืฅ. ืื™ืฆื˜ ืขืก ื‘ืœื™ื™ื‘ื˜ ื ืึธืจ ืฆื• ืฆื•ืœื™ื™ื’ืŸ ืึทืœืข ื“ืขื ืฆื• ื“ื™ ืงื•ื‘ืขืจื ืขื˜ืขืก ืงื ื•ื™ืœ. ืฆื• ืฆืขื•ื•ื™ืงืœืขืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ, ืื™ืจ ืงืขื ืขืŸ, ืคื•ืŸ ืงื•ืจืก, ื ื•ืฆืŸ ื“ื™ kubectl application -f ื‘ืึทืคึฟืขืœ, ืึธื‘ืขืจ ื“ื™ ืคึผืœื•ื’ื™ืŸ ืงืขื ืขืŸ ื˜ืึธืŸ ื“ืึธืก ืคึฟืึทืจ ืื•ื ื“ื–. ื“ืึธืก ืื™ื– ื•ื•ืึธืก ื•ื•ืขื˜ ื–ื™ื™ืŸ ื’ืขื•ื•ื™ื–ืŸ ืื•ื™ืฃ ื“ืขื ืขืงืจืึทืŸ ื ืึธืš ืžื™ืจ ื‘ืขื˜ืŸ Eclipse JKube ืฆื• ื•ื™ืกืคื™ืจืŸ ื“ื™ mvn k8s: ืฆื•ืœื™ื™ื’ืŸ ืึทืคึผืœื™ื™ื™ื ื’ ืึทืจื‘ืขื˜:

~/work/repos/eclipse-jkube-demo-project : $ mvn k8s:apply
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- kubernetes-maven-plugin:1.0.0-rc-1:apply (default-cli) @ random-generator ---
[INFO] k8s: Using Kubernetes at https://192.168.39.145:8443/ in namespace default with manifest /home/rohaan/work/repos/eclipse-jkube-demo-project/target/classes/META-INF/jkube/kubernetes.yml 
[INFO] k8s: Using namespace: default
[INFO] k8s: Creating a Service from kubernetes.yml namespace default name random-generator
[INFO] k8s: Created Service: target/jkube/applyJson/default/service-random-generator.json
[INFO] k8s: Creating a Deployment from kubernetes.yml namespace default name random-generator
[INFO] k8s: Created Deployment: target/jkube/applyJson/default/deployment-random-generator.json
[INFO] k8s: HINT: Use the command `kubectl get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  7.306 s
[INFO] Finished at: 2020-08-10T11:40:57+05:30
[INFO] ------------------------------------------------------------------------
~/work/repos/eclipse-jkube-demo-project : $ kubectl get pods -w
NAME                                                     READY   STATUS             RESTARTS   AGE
random-generator-58b7847d7f-9m9df                        0/1     Running            0          7s
random-generator-58b7847d7f-9m9df                        1/1     Running            0          17s
^C~/work/repos/eclipse-jkube-demo-project : $ kubectl get svc
NAME                                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)           AGE
io-openliberty-sample-getting-started   NodePort    10.110.4.104    <none>        9080:30570/TCP    44h
kubernetes                              ClusterIP   10.96.0.1       <none>        443/TCP           18d
random-generator                        NodePort    10.97.172.147   <none>        8080:32186/TCP    22s
~/work/repos/eclipse-jkube-demo-project : $ curl `minikube ip`:32186/random | jq .
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    45    0    45    0     0   1800      0 --:--:-- --:--:-- --:--:--  1875
{
  "id": "42e5571f-a20f-44b3-8184-370356581d10"
}

ืฉืจื™ื˜ 6. ืึทื ื“ืขืคึผืœื•ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคื•ืŸ ื“ื™ Kubernetes ืงื ื•ื™ืœ

ืฆื• ื˜ืึธืŸ ื“ืึธืก, ื“ื™ ืึทื ื“ืขืคึผืœื•ื™ ืึทืจื‘ืขื˜ ืื™ื– ื’ืขื ื™ืฆื˜, ื•ื•ืึธืก ืคืฉื•ื˜ ืจื™ืžื•ื•ื•ื– ืึทืœืข ืจืขืกื•ืจืกืŸ ื•ื•ืึธืก ื–ืขื ืขืŸ ื’ืขื•ื•ืขืŸ ื’ืขื•ื•ืขื ื“ื˜ ืื™ืŸ ื“ื™ ืคืจื™ืขืจื“ื™ืงืข ืฉืจื™ื˜, ื“ืึธืก ืื™ื–, ื•ื•ืขืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืึทืจื‘ืขื˜ ืื™ื– ืขืงืกืึทืงื™ื•ื˜ืึทื“. ื“ืึธืก ืื™ื– ื•ื•ืึธืก ืžื™ืจ ื•ื•ืขืœืŸ ื–ืขืŸ ืื•ื™ืฃ ื“ืขื ืขืงืจืึทืŸ ื ืึธืš ืžื™ืจ ื‘ืขื˜ืŸ Eclipse JKube ืฆื• ื“ื•ืจื›ืคื™ืจืŸ ื“ื™ mvn k8s:undeploy undeploy ืึทืจื‘ืขื˜:

~/work/repos/eclipse-jkube-demo-project : $ kubectl get all
NAME                                    READY   STATUS    RESTARTS   AGE
pod/random-generator-58b7847d7f-9m9df   1/1     Running   0          5m21s

NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
service/kubernetes         ClusterIP   10.96.0.1       <none>        443/TCP          18d
service/random-generator   NodePort    10.97.172.147   <none>        8080:32186/TCP   5m21s

NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/random-generator   1/1     1            1           5m21s

NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/random-generator-58b7847d7f   1         1         1       5m21s
~/work/repos/eclipse-jkube-demo-project : $ mvn k8s:undeploy
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- kubernetes-maven-plugin:1.0.0-rc-1:undeploy (default-cli) @ random-generator ---
[INFO] k8s: Using Kubernetes at https://192.168.39.145:8443/ in namespace default with manifest /home/rohaan/work/repos/eclipse-jkube-demo-project/target/classes/META-INF/jkube/kubernetes.yml 
[INFO] k8s: Using namespace: default
[INFO] k8s: Deleting resource Deployment default/random-generator
[INFO] k8s: Deleting resource Service default/random-generator
[INFO] k8s: HINT: Use the command `kubectl get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  3.412 s
[INFO] Finished at: 2020-08-10T11:46:22+05:30
[INFO] ------------------------------------------------------------------------
~/work/repos/eclipse-jkube-demo-project : $ kubectl get pods -w
^C~/work/repos/eclipse-jkube-demo-project : $ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   18d
~/work/repos/eclipse-jkube-demo-project : $

ื•ื•ืึธืก ืึทื ื“ืขืจืฉ ืงืขื ืขืŸ ืื™ืจ ื˜ืึธืŸ ืžื™ื˜ Eclipse JKube

ืึทื–ื•ื™, ืžื™ืจ ื’ืขืงื•ืงื˜ ืื•ื™ืฃ ื“ื™ ื”ื•ื™ืคึผื˜ ืฆื™ืœ ื˜ืึทืกืงืก ืคื•ืŸ Eclipse JKube ืื•ืŸ Kubernetes Maven Plugin, ื•ื•ืึธืก ืคืึทืกื™ืœืึทื˜ื™ื™ื˜ ื“ื™ ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ืคื•ืŸ Java ืึทืคึผืœืึทืงื™ื™ืฉืึทื ื– ืคึฟืึทืจ ื“ื™ Kubernetes ืคึผืœืึทื˜ืคืึธืจืžืข. ืื•ื™ื‘ ืื™ืจ ื˜ืึธืŸ ื ื™ืฉื˜ ื•ื•ืขืœืŸ ืฆื• ืงืขืกื™ื™ื“ืขืจ ืึทืจื™ื™ึทืŸ ื“ื™ ื˜ืึทืกืงืก ืคึฟื•ืŸ ื“ื™ ืงืœืึทื•ื•ื™ืึทื˜ื•ืจ, ืื™ืจ ืงืขื ืขืŸ ืฉืจื™ื™ึทื‘ืŸ ื–ื™ื™ ืื™ืŸ ื“ื™ ืคึผืœื•ื’ื™ืŸ ืงืึทื ืคื™ื’ื™ืขืจื™ื™ืฉืึทืŸ, ืœืžืฉืœ, ื•ื•ื™ ื“ืึธืก:

<plugin>
     <groupId>org.eclipse.jkube</groupId>
     <artifactId>kubernetes-maven-plugin</artifactId>
     <version>${project.version}</version>
     <executions>
         <execution>
             <goals>
                  <goal>build</goal>
                  <goal>resource</goal>
                  <goal>apply</goal>
             </goals>
         </execution>
     </executions>
</plugin>

ืขืก ืžื•ื–ืŸ ื–ื™ื™ืŸ ื’ืขื–ืึธื’ื˜ ืึทื– ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ ืžื™ืจ ื”ืึธื‘ืŸ ื ื™ืฉื˜ ื‘ืึทื˜ืจืึทื›ื˜ ืึทืœืข ื“ื™ ืฆื™ืœ ื˜ืึทืกืงืก ืื™ืŸ Eclipse JKube ืื•ืŸ Kubernetes Maven Plugin, ืึทื–ื•ื™ ืžื™ืจ ืฆื•ืฉื˜ืขืœืŸ ืื™ืŸ ื˜ืึทื‘ืœืข 2 ืึท ืจืฉื™ืžื” ืคื•ืŸ ื ืึธืš ื˜ืึทืกืงืก ื•ื•ืึธืก ืงืขืŸ ืื•ื™ืš ื–ื™ื™ืŸ ื ื•ืฆื™ืง ืคึฟืึทืจ ืื™ืจ.

ื˜ื™ืฉ 2. ื ืึธืš ืขืงืœื™ืคึผืกืข ื“ื–ืฉืงื•ื‘ืข ืฆื™ืœ ื˜ืึทืกืงืก.

ืึทืจื‘ืขื˜
ื‘ื™ื ืข
ื‘ืึทืฉืจื™ื™ึทื‘ื•ื ื’

k8s: ืงืœืึธืฅ
VALIDATE
ื‘ืึทืงื•ืžืขืŸ ืœืึธื’ืก ืคื•ืŸ ืึท ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืคืœื™ืกื ื“ื™ืง ืื•ื™ืฃ Kubernetes.

k8s: ื“ื™ื‘ืึทื’
ืคึผืขืงืœ
ืขืคึฟืขื ืขืŸ ืึท ื“ื™ื‘ืึทื’ ืคึผืึธืจื˜ ืึทื–ื•ื™ ืื™ืจ ืงืขื ืขืŸ ื“ื™ื‘ื•ื’ ื“ื™ื™ืŸ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืคืœื™ืกื ื“ื™ืง ืื•ื™ืฃ Kubernetes ื’ืœื™ื™ึทืš ืคึฟื•ืŸ ื“ื™ IDE.

k8s: ื“ื™ืคึผืœื•ื™
ื™ื ืกื˜ืึทืœื™ืจืŸ
ืฉืึทืคึฟืŸ ืึท ื’ืึธืคึผืœ ืคึฟืึทืจ ื“ื™ ื™ื ืกื˜ืึทืœืœ ืึทืจื‘ืขื˜ ืื•ืŸ ืึทืคึผืœื™ื™ื™ื ื’ ื“ื™ ื“ื–ืฉืขื ืขืจื™ื™ื˜ืึทื“ ืžืึทื ื™ืคืขืกืฅ ืฆื• ื“ื™ Kubernetes ืงื ื•ื™ืœ ืื™ืŸ ื“ื™ ื–ืขืœื‘ืข ื•ื•ืขื’ ื•ื•ื™ ืื™ืŸ ื“ืขื ืคืึทืœ ืคื•ืŸ ื“ื™ ืฆื•ืœื™ื™ื’ืŸ ืึทืจื‘ืขื˜.

ืง8ืก: ื•ื•ืึทืš
ืคึผืขืงืœ
ืึธื˜ืึทืžืึทื˜ื™ืง ื”ื™ื™ืก ื“ื™ืคึผืœื•ื™ืžืึทื ื˜ ืคื•ืŸ ืึท ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ื“ื•ืจืš ื˜ืจืึทืงื™ื ื’ ื–ื™ื™ึทืŸ ื ืึทืžืขืกืคึผืึทืกืข.

ื“ื™ืคึผืœื•ื™ื™ื ื’ Java ืึทืคึผืคึผืœื™ืงืึทื˜ื™ืึธื ืก ืื•ื™ืฃ Red Hat OpenShift ื ื™ืฆืŸ ื“ื™ OpenShift Maven ืคึผืœื•ื’ื™ืŸ

ืฆื• ืฆืขื•ื•ื™ืงืœืขืŸ ื“ื™ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืคึฟื•ืŸ ืื•ื ื“ื–ืขืจ ื‘ื™ื™ืฉืคึผื™ืœ ืื•ื™ืฃ ื“ื™ Red Hat OpenShift ืคึผืœืึทื˜ืคืึธืจืžืข, ืžื™ืจ ื ื•ืฆืŸ ื“ืขื ืคึผืœื•ื’ื™ืŸ OpenShift Maven. ื“ืขืจ ื‘ืœื•ื™ื– ื—ื™ืœื•ืง ืื™ื– ืึทื– ื“ื™ ืึทืจื‘ืขื˜ ืคึผืจืขืคื™ืงืก ื•ื•ืขื˜ ื˜ื•ื™ืฉืŸ ืคื•ืŸ k8s ืฆื• oc. ื“ื•ืจืš ืคืขืœื™ืงื™ื™ึทื˜ ื“ื™ Kubernetes Maven ืคึผืœื•ื’ื™ืŸ ื“ืึธืงืงืขืจ-ืึทืกืขืžื‘ืึทืœื–, ืื•ืŸ ื“ื™ OpenShift Maven ืคึผืœื•ื’ื™ืŸ - ืึทืกืขืžื‘ืœื™ื– S2I. ืžื™ืจ ื˜ืึธืŸ ื ื™ื˜ ืžืึทื›ืŸ ืงื™ื™ืŸ ืขื ื“ืขืจื•ื ื’ืขืŸ ืฆื• ืื•ื ื“ื–ืขืจ ืคึผืจื•ื™ืขืงื˜, ืึทื—ื•ืฅ ืคึฟืึทืจ ืจื™ืžื•ื•ื•ื™ื ื’ ื“ื™ jkube.generator.name ืคืึทืจืžืึธื’, ื•ื•ื™ื™ึทืœ ืขืก ืื™ื– ื ื™ืฉื˜ ืคืืจืœืื ื’ื˜ ื•ื•ืขืŸ ืคึผื•ืฉื™ื ื’ ืฆื• ื“ื™ ืจืขื’ื™ืกื˜ืจื™ (ื‘ืขืฉืึทืก ื“ื™ ื‘ื•ื™ืขืŸ ืคืึทืกืข, OpenShift ืฉื˜ืขืœืŸ ื“ื™ ื‘ื™ืœื“ ืื™ืŸ ื–ื™ื™ืŸ ื™ื ืขืจืœืขืš ืจืขื’ื™ืกื˜ืจื™). ืื•ืŸ ื“ืึธืก ืื™ื– ื•ื•ืึธืก ื•ื•ืขื˜ ื“ืขืจืฉื™ื™ึทื ืขืŸ ืื•ื™ืฃ ื“ืขื ืขืงืจืึทืŸ ื•ื•ืขืŸ ืžื™ืจ ืœื•ื™ืคืŸ ืื•ื ื“ื–ืขืจ ื‘ื™ื™ืฉืคึผื™ืœ, ืื™ืŸ ื•ื•ืึธืก, ื“ื•ืจืš ื“ืขื ื•ื•ืขื’, ืžื™ืจ ื“ื•ืจื›ืคื™ืจืŸ ืฆื™ืœ ื˜ืึทืกืงืก ื ื™ื˜ ืื™ื™ืŸ ืื™ืŸ ืึท ืฆื™ื™ึทื˜, ืึธื‘ืขืจ ืึทืœืข ืื™ืŸ ืึทืžืึธืœ:

~/work/repos/eclipse-jkube-demo-project : $ mvn oc:build oc:resource oc:apply
[INFO] Scanning for projects...
[INFO] 
[INFO] ----------------------< meetup:random-generator >-----------------------
[INFO] Building random-generator 0.0.1
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] 
[INFO] --- openshift-maven-plugin:1.0.0-rc-1:build (default-cli) @ random-generator ---
[INFO] oc: Using OpenShift build with strategy S2I
[INFO] oc: Running in OpenShift mode
[INFO] oc: Running generator spring-boot
[INFO] oc: spring-boot: Using Docker image quay.io/jkube/jkube-java-binary-s2i:0.0.7 as base / builder
[INFO] oc: [random-generator:0.0.1] "spring-boot": Created docker source tar /home/rohaan/work/repos/eclipse-jkube-demo-project/target/docker/random-generator/0.0.1/tmp/docker-build.tar
[INFO] oc: Adding to Secret pullsecret-jkube
[INFO] oc: Using Secret pullsecret-jkube
[INFO] oc: Creating BuildServiceConfig random-generator-s2i for Source build
[INFO] oc: Creating ImageStream random-generator
[INFO] oc: Starting Build random-generator-s2i
[INFO] oc: Waiting for build random-generator-s2i-1 to complete...
[INFO] oc: Caching blobs under "/var/cache/blobs".
[INFO] oc: Getting image source signatures
[INFO] oc: Copying blob sha256:cf0f3ebe9f536c782ab3835049cfbd9a663761ded9370791ef6ea3965c823aad
[INFO] oc: Copying blob sha256:57de4da701b511cba33bbdc424757f7f3b408bea741ca714ace265da9b59191a
[INFO] oc: Copying blob sha256:f320f94d91a064281f5127d5f49954b481062c7d56cce3b09910e471cf849050
[INFO] oc: Copying config sha256:52d6788fcfdd39595264d34a3959464a5dabc1d4ef0ae188802b20fc2d6a857b
[INFO] oc: Writing manifest to image destination
[INFO] oc: Storing signatures
[INFO] oc: Generating dockerfile with builder image quay.io/jkube/jkube-java-binary-s2i:0.0.7
[INFO] oc: STEP 1: FROM quay.io/jkube/jkube-java-binary-s2i:0.0.7
[INFO] oc: STEP 2: LABEL "io.openshift.build.source-location"="/tmp/build/inputs"       "io.openshift.build.image"="quay.io/jkube/jkube-java-binary-s2i:0.0.7"
[INFO] oc: STEP 3: ENV JAVA_APP_DIR="/deployments"     OPENSHIFT_BUILD_NAME="random-generator-s2i-1"     OPENSHIFT_BUILD_NAMESPACE="default"
[INFO] oc: STEP 4: USER root
[INFO] oc: STEP 5: COPY upload/src /tmp/src
[INFO] oc: STEP 6: RUN chown -R 1000:0 /tmp/src
[INFO] oc: STEP 7: USER 1000
[INFO] oc: STEP 8: RUN /usr/local/s2i/assemble
[INFO] oc: INFO S2I source build with plain binaries detected
[INFO] oc: INFO S2I binary build from fabric8-maven-plugin detected
[INFO] oc: INFO Copying binaries from /tmp/src/deployments to /deployments ...
[INFO] oc: random-generator-0.0.1.jar
[INFO] oc: INFO Copying deployments from deployments to /deployments...
[INFO] oc: '/tmp/src/deployments/random-generator-0.0.1.jar' -> '/deployments/random-generator-0.0.1.jar'
[INFO] oc: STEP 9: CMD /usr/local/s2i/run
[INFO] oc: STEP 10: COMMIT temp.builder.openshift.io/default/random-generator-s2i-1:48795e41
[INFO] oc: time="2020-08-10T06:37:49Z" level=info msg="Image operating system mismatch: image uses "", expecting "linux""
[INFO] oc: time="2020-08-10T06:37:49Z" level=info msg="Image architecture mismatch: image uses "", expecting "amd64""
[INFO] oc: Getting image source signatures
[INFO] oc: Copying blob sha256:d8e1f35641acb80b562f70cf49911341dfbe8c86f4d522b18efbf3732aa74223
[INFO] oc: Copying blob sha256:b6f081e4b2b6de8be4b1dec132043d14c121e968384dd624fb69c2c07b482edb
[INFO] oc: Copying blob sha256:b7139ad07aa8ce4ed5a132f7c5cc9f1de0f5099b5e155027a23d57f7fbe78b16
[INFO] oc: Copying blob sha256:98972fc90a1108315cc5b05b2c691a0849a149727a7b81e76bc847ac2c6d9714
[INFO] oc: Copying config sha256:27aaadaf28e24856a66db962b88118b8222b61d79163dceeeed869f7289bc230
[INFO] oc: Writing manifest to image destination
[INFO] oc: Storing signatures
[INFO] oc: --> 27aaadaf28e
[INFO] oc: 27aaadaf28e24856a66db962b88118b8222b61d79163dceeeed869f7289bc230
[INFO] oc: Getting image source signatures
[INFO] oc: 
[INFO] oc: Pushing image image-registry.openshift-image-registry.svc:5000/default/random-generator:0.0.1 ...
[INFO] oc: Copying blob sha256:f320f94d91a064281f5127d5f49954b481062c7d56cce3b09910e471cf849050
[INFO] oc: Copying blob sha256:cf0f3ebe9f536c782ab3835049cfbd9a663761ded9370791ef6ea3965c823aad
[INFO] oc: Copying blob sha256:57de4da701b511cba33bbdc424757f7f3b408bea741ca714ace265da9b59191a
[INFO] oc: Copying blob sha256:98972fc90a1108315cc5b05b2c691a0849a149727a7b81e76bc847ac2c6d9714
[INFO] oc: Copying config sha256:27aaadaf28e24856a66db962b88118b8222b61d79163dceeeed869f7289bc230
[INFO] oc: Writing manifest to image destination
[INFO] oc: Storing signatures
[INFO] oc: Successfully pushed image-registry.openshift-image-registry.svc:5000/default/random-generator@sha256:aa9e1a380c04ef9174ba56459c13d44420ebe653ebf32884d60fe4306b17306d
[INFO] oc: Push successful
[INFO] oc: Build random-generator-s2i-1 in status Complete
[INFO] oc: Found tag on ImageStream random-generator tag: sha256:aa9e1a380c04ef9174ba56459c13d44420ebe653ebf32884d60fe4306b17306d
[INFO] oc: ImageStream random-generator written to /home/rohaan/work/repos/eclipse-jkube-demo-project/target/random-generator-is.yml
[INFO] 
[INFO] --- openshift-maven-plugin:1.0.0-rc-1:resource (default-cli) @ random-generator ---
[INFO] oc: Using docker image name of namespace: default
[INFO] oc: Running generator spring-boot
[INFO] oc: spring-boot: Using Docker image quay.io/jkube/jkube-java-binary-s2i:0.0.7 as base / builder
[INFO] oc: jkube-controller: Adding a default DeploymentConfig
[INFO] oc: jkube-service: Adding a default service 'random-generator' with ports [8080]
[INFO] oc: jkube-healthcheck-spring-boot: Adding readiness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 10 seconds
[INFO] oc: jkube-healthcheck-spring-boot: Adding liveness probe on port 8080, path='/actuator/health', scheme='HTTP', with initial delay 180 seconds
[INFO] oc: jkube-revision-history: Adding revision history limit to 2
[INFO] 
[INFO] --- openshift-maven-plugin:1.0.0-rc-1:apply (default-cli) @ random-generator ---
[INFO] oc: Using OpenShift at https://api.crc.testing:6443/ in namespace default with manifest /home/rohaan/work/repos/eclipse-jkube-demo-project/target/classes/META-INF/jkube/openshift.yml 
[INFO] oc: OpenShift platform detected
[INFO] oc: Using project: default
[INFO] oc: Creating a Service from openshift.yml namespace default name random-generator
[INFO] oc: Created Service: target/jkube/applyJson/default/service-random-generator.json
[INFO] oc: Creating a DeploymentConfig from openshift.yml namespace default name random-generator
[INFO] oc: Created DeploymentConfig: target/jkube/applyJson/default/deploymentconfig-random-generator.json
[INFO] oc: Creating Route default:random-generator host: null
[INFO] oc: HINT: Use the command `oc get pods -w` to watch your pods start up
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  01:07 min
[INFO] Finished at: 2020-08-10T12:08:00+05:30
[INFO] ------------------------------------------------------------------------
~/work/repos/eclipse-jkube-demo-project : $ oc get pods -w
NAME                           READY     STATUS      RESTARTS   AGE
random-generator-1-deploy      1/1       Running     0          14s
random-generator-1-vnrm9       0/1       Running     0          11s
random-generator-s2i-1-build   0/1       Completed   0          1m
random-generator-1-vnrm9   1/1       Running   0         24s
random-generator-1-deploy   0/1       Completed   0         28s
~/work/repos/eclipse-jkube-demo-project : $ oc get routes
NAME                HOST/PORT                                    PATH      SERVICES            PORT      TERMINATION   WILDCARD
random-generator    random-generator-default.apps-crc.testing              random-generator    8080                    None
~/work/repos/eclipse-jkube-demo-project : $ curl random-generator-default.apps-crc.testing/random 
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload  Upload   Total   Spent    Left  Speed
100    45    0    45    0     0   1666      0 --:--:-- --:--:-- --:--:--  1730
{
"id": "d80052d9-2f92-43cb-b9eb-d7cffb879798"
}
~/work/repos/eclipse-jkube-demo-project : $

ื•ื•ื™ื“ืขื ืœืขืงืฆื™ืข

ืฆื• ืœืขืจื ืขืŸ ืžืขืจ ื•ื•ืขื’ืŸ ื•ื•ื™ ืฆื• ืžืึทื›ืŸ Kubernetes ืึทื ื˜ื•ื•ื™ืงืœื•ื ื’ ื’ืจื™ื ื’ืขืจ ืžื™ื˜ Eclipse JKube, ื”ื™ื˜ืŸ ื“ืขื ื•ื•ื™ื“ืขื ื˜ื•ื˜ืึธืจื™ืึทืœ ืื•ื™ืฃ ื•ื•ื™ ืฆื• ื’ืขืฉื•ื•ื™ื ื“ ืฆืขื•ื•ื™ืงืœืขืŸ ืึท ืคึผืฉื•ื˜ ืกืคึผืจื™ื ื’ ื‘ืึธืึธื˜ ืึทืคึผืœืึทืงื™ื™ืฉืึทืŸ ืื•ื™ืฃ Minikube:

ืกืึธืฃ

ืื™ืŸ ื“ืขื ืึทืจื˜ื™ืงืœ, ืžื™ืจ ื’ืขื•ื•ื™ื–ืŸ ื•ื•ื™ Eclipse JKube ืžืื›ื˜ ืœืขื‘ืŸ ื’ืจื™ื ื’ืขืจ ืคึฟืึทืจ ืึท Java ื“ืขื•ื•ืขืœืึธืคึผืขืจ ื•ื•ืขืŸ ืืจื‘ืขื˜ืŸ ืžื™ื˜ Kubernetes. ืžืขืจ ืื™ื ืคึฟืึธืจืžืึทืฆื™ืข ืื•ื™ืฃ Eclipse JKube ืงืขื ืขืŸ ื–ื™ื™ืŸ ื’ืขืคึฟื•ื ืขืŸ ืื™ืŸ ืคึผืจื•ื™ืขืงื˜ ื•ื•ืขื‘ื–ื™ื™ึทื˜ืœ ืื•ืŸ ื’ื™ื˜ื”ื•ื‘.

ืžืงื•ืจ: www.habr.com

ืœื™ื™ื’ืŸ ืึท ื‘ืึทืžืขืจืงื•ื ื’