Nhảy tới nội dung

· Một phút để đọc
ManhPT

Hướng dẫn cài đặt và cấu hình cert-manager cho website sử dụng ingress-nginx với letsencrypt. Bạn có thể tham khảo tài liệu chính thống về cert-manager tại đây: https://cert-manager.io/docs/.

Kể từ ngày 24/07/2018, Google release Chrome 68 có tính năng đánh dấu các trang web không dùng HTTPS là “Không an toàn” nhằm xây dựng trình duyệt an toàn hơn. Việc này đã diễn ra trong vòng 1 năm. Hiện tại, Microsoft Edge (Chromium) vẫn đang duy trì điều này. Điều này khiến việc triển khai HTTPS cho website của bạn trở thành một yêu cầu bắt buộc.

Trong bài viết này, mình sẽ hướng dẫn cấu hình cert-manager cho nginx-ingress để tự động hóa hoàn toàn việc issue và renew chứng chỉ https cho website của bạn hoàn toàn miễn phí. Tất nhiên bài viết này chỉ áp dụng cho hệ thống sử dụng kubernetes. Trong thời điểm viết bài thì mình sử dụng K3S. Bạn có thể tham khảo cách cài đặt K3S tại đây.

Chuẩn bị

Cài đặt cert-manager

Để cài đặt cert-manager thì bạn chỉ cần làm đúng theo những hướng dẫn từ tài liệu chính hãng tại đây: https://cert-manager.io/docs/installation/kubernetes/#installing-with-helm Tạo namespace cert-manager:

kubectl create namespace cert-manager

Tạo một helm release mới:

# Helm v3+
helm install \
cert-manager jetstack/cert-manager \
--namespace cert-manager \
--version v1.0.3 \
--set installCRDs=true

# Helm v2
helm install \
--name cert-manager \
--namespace cert-manager \
--version v1.0.3 \
jetstack/cert-manager \
--set installCRDs=true

Cấu hình cert-manager ClusterIssuer

Bạn có 2 sự lựa chọn, self signed hoặc letsencrypt. Vui lòng đọc kỹ hướng dẫn trước khi sử dụng 😁.

Self signed

Sử dụng self signed certificate nếu website của bạn sử dụng kết hợp với CloudFlare SSL/TLS và sử dụng encryption mode là Full.

Tạo một template file selfsigned.issuer.yaml với nội dung như sau:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned
namespace: cert-manager
spec:
selfSigned: {}

Tạo Issuer từ template trên:

kubectl --namespace cert-manager apply -f selfsigned.issuer.yaml

Let's Encrypt

Sử dụng Letsencrypt nếu website của bạn public trực tiếp ra internet hoặc sử dụng kết hợp CloudFlare SSL/TLS với encryption mode là Full (strict).

Tạo một template file letsencrypt-prod.issuer.yaml với nội dung như sau:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
namespace: cert-manager
spec:
acme:
# The ACME server URL
server: https://acme-v02.api.letsencrypt.org/directory
# Email address used for ACME registration
email: [email protected]
# Name of a secret used to store the ACME account private key
privateKeySecretRef:
name: letsencrypt-prod
# Enable the HTTP-01 challenge provider
solvers:
- http01:
ingress:
class: nginx

Chú ý cập nhật thông tin:

  • [email protected] - thay bằng email của bạn, Let's Encrypt sẽ liên hệ với bạn qua email này

Tạo Issuer từ template trên:

kubectl --namespace cert-manager apply -f letsencrypt-prod.issuer.yaml

Cấu hình ingress

Do chúng ta sử dụng kind: ClusterIssuer nên ingress ở các namespace khác cert-manager vẫn có thể sử dụng được.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: test-ingress
annotations:
kubernetes.io/ingress.class: nginx
cert-manager.io/cluster-issuer: selfsigned
spec:
tls:
- secretName: test-ingress-tls
hosts:
- yourdomain.com
rules:
- host: yourdomain.com
http:
paths:
- path:
backend:
serviceName: your-service-name
servicePort: 80

Chú ý cập nhật các thông tin:

  • yourdomain.com - thay bằng domain thật của bạn
  • your-service-name - thay bằng service name của bạn

Quan trọng nhất là cert-manager.io/cluster-issuer: selfsigned, cert-manager sẽ dựa trên các annotations này cùng với thông tin của mỗi Ingress để thực hiện việc issue và renew certificate.

  • cert-manager.io/cluster-issuer là annotation yêu cầu sử dụng ClusterIssuer
  • selfsigned là tên của ClusterIssuer được chỉ định

· Một phút để đọc
ManhPT

K3S là một phiên bản nhỏ và nhẹ của Kubernetes mà bạn có thể sử dụng trên rất nhiều môi trường thiết bị khác nhau. Bài viết này không nhằm mục đích giới thiệu K3S nên các bạn có thể tìm hiểu thêm về K3S tại đây https://k3s.io/ hoặc https://github.com/rancher/k3s/blob/master/README.md trước khi đọc tiếp.

Để có thể cài đặt và sử dụng K3S thì các bạn cũng nên tham khảo yêu cầu hệ thống của K3S trước tại: https://rancher.com/docs/k3s/latest/en/installation/installation-requirements/. Nếu bạn đã chuẩn bị đầy đủ môi trường theo đúng yêu cầu của K3S thì bắt đầu thôi.

Cài đặt K3S với tất cả cấu hình mặc định:

curl -sfL https://get.k3s.io | sh -

Sau khi chạy script cài đặt trên thì:

  • K3S sẽ được cấu hình để tự động restart sau khi node bị reboot hoặc process bị lỗi hay bị kill.
  • Vài công cụ hỗ trợ cũng sẽ được cài đặt đó là: kubectl, crictl, ctr, k3s-killall.sh, and k3s-uninstall.sh.
  • Một file chứa kubeconfig sẽ được ghi vào /etc/rancher/k3s/k3s.yamlkubectl sẽ tự đụng sử dụng file này.

Chú ý:

Cài đặt K3S với custom config

Không sử dụng Traefik Ingress

curl -sfL https://get.k3s.io | sh -s - --disable traefik

Không sử dụng cả Traefik Ingress và Local-Path Storage

curl -sfL https://get.k3s.io | sh -s - --disable traefik,local-storage

Custom range cho NodePort Service

curl -sfL https://get.k3s.io | sh -s - --kube-apiserver-arg service-node-port-range=2000-32767

Cập nhật TLS cho phép remote kubectl thông qua public IP

curl -sfL https://get.k3s.io | sh -s - --tls-san=123.123.123.123
  • 123.123.123.123 - thay bằng public IP của cluster load balancer

Cập nhật hoặc thay đổi cấu hình K3S

Kubernetes nói chung và K3S nói riêng phát triển tương đối nhanh với cộng đồng lớn. Để cập nhật phiên bản mới hay thay đổi cấu hình cluster thì bạn chỉ cần chạy lại câu lệnh cài đặt với cấu hình mong muốn. Script cài đặt sẽ chạy lại các bước giống như lúc cài đặt.

Việc cập nhật phiên bản mới không nên diễn ra thường xuyên mà nên có kế hoạch trước và cũng nên đợi phiên bản mới chứng minh được tính ổn định rồi bạn mới upgrade cũng không muộn.

Thêm node cho cluster

Để thêm 1 node mới thì câu lệnh cũng rất đơn giản:

curl -sfL https://get.k3s.io | K3S_URL=https://<myserver>:6443 K3S_TOKEN=<mynodetoken> sh -
  • <myserver> - thay bằng IP của master node (nên sử dụng IP LAN)
  • <mynodetoken> - thay bằng token của master node được ghi tại /var/lib/rancher/k3s/server/node-token

Xóa cài đặt K3S

Nếu bạn cài đặt k3s sử dụng script thì script để xóa k3s cũng sẽ được cài đặt tự động. Để xóa k3s khỏi một server node:

/usr/local/bin/k3s-uninstall.sh

Để xóa k3s khỏi một agent node:

/usr/local/bin/k3s-agent-uninstall.sh

· Một phút để đọc
ManhPT

Chuyển từ MacOS hay Ubuntu về sử dụng Windows

Mình gần như đã từng là fan của Apple khi mà sử dụng iPhone, Macbook cho cuộc sống và công việc. Việc cho phép cài đặt phần mềm qua dòng lệnh khá là lý tưởng với một developer như mình.

Ngoài ra, ngày còn khờ dại, đọc được thông tin đâu đó về việc NodeJs được tạo ra trên MacOS đã khiến mình quyết định mua chiếc Macbook đầu tiên - mình là một NodeJS Developer.

Chocolatey và sự ảnh hưởng của thói quen trên MacOS

Sau khoảng 5 năm liên tục sử dụng MacOS thì cuối cùng mình đã quyết định quay trở lại với Windows. Lý do là muốn một sự thay đổi và cũng là để phục vụ niềm yêu thích chơi game (thực ra là sau khi xem phim The Witcher). Và đương nhiên khi trở lại sử dụng windows mình đã gặp phải một số vấn đề. Vấn đề lớn nhất mà mình thấy là việc cài đặt phần mềm và các công cụ phát triển phần mềm.

Search một hồi thì cũng tìm ra Chocolatey, người anh em cùng cha khác ông nội với Homebrew (MacOS) và Snap (Ubuntu). Trải nghiệm sử dụng khá tương đồng, chỉ tiếc là số lượng trong thư viện của nó hơi thua kém so với Homebrew. Bạn có thể cài đặt chocolatey theo hướng dẫn tại đây: https://chocolatey.org/install.

Vấn đề về quản lý nhiều nodejs version trên windows

Với Chocolatey bạn có thể cài đặt hầu hết những phần mềm phổ biến, thậm chí có thể upgrade các phần mềm đã được cài đặt qua Chocolatey chỉ với một câu lệnh. Như mình đã nói ở trên, mình là một NodeJS Developer; và mình nhanh chóng nhận ra vấn đề: quản lý và sử dụng nhiều nodejs version cùng lúc.

Tất nhiên là mình hay bạn đều nghĩ ngay đến nvm. Nghĩ sao là làm vậy thì rất tiếc là nvm mà chúng tay vẫn hay dùng trên MacOS hay các linux distro khác lại không hoạt động trên windows. Search luôn cụm từ "nvm windows" thì cũng tìm ra được một tool phù hợp và thậm chí còn có thể cài đặt được qua Chocolatey: nvm-windows.

choco install -y nvm

Để cài đặt và sử dụng nodejs với nvm thì bạn chỉ cần:

# nvm install <version>
# nvm use <version>
nvm install 12.16.1
nvm use 12.16.1
node --version # should show 12.16.1
nvm install 10.19.0
nvm use 10.19.0
node --version # should show 10.19.0

Hoặc bạn có thể tham khảo thêm tại đây: https://github.com/coreybutler/nvm-windows#usage

Bước này optional

Có vẻ ổn rồi, mình cài đặt luôn nodejs-lts để sử dụng; nodejs-lts để tạo một bản nodejs và npm global cho phép lưu giữ các npm global packages. Bạn sẽ không bị mất chúng sau mỗi lần upgrade hoặc đổi version nodejs.

Trên MacOS, nvm thường tự động nhận diện bản nodejs global và coi nó là bản "nodejs system". Nếu muốn thay đổi giữa nodejs system và các nodejs version khác:

nvm use system
nvm use default
nvm use 12.16.1

NVM trên MacOS cho phép bạn chuyển đổi qua lại giữa "nodejs system" và các version nhất định. Nhưng rất tiếc là nvm-windows lại không có khả năng đó.

Cài đặt Nodejs và Yarn

Cuối cùng thì mình cũng tìm ra được vị cứu tinh, là Yarn. Rất may là có thể cài đặt yarn thông qua Chocolatey:

choco install -y yarn

Bạn cần chạy lệnh này trong PowerShell hoặc CMD với quyền Administrator. Sau khi cài đặt yarn thành công, bạn có thể cài đặt các global package như sau:

# yarn global add <package>
yarn global add lerna
yarn global add firebase-tools

Kết quả

Bây giờ thì các npm global packages bạn hay dùng sẽ được quản lý bởi yarn. Chúng sẽ không biến mất khi bạn thay đổi node version với nvm. Let's write some code!

· Một phút để đọc
ManhPT

Khi Cloud Native tiếp tục đà phát triển mạnh mẽ trong cộng đồng, ngày càng nhiều tổ chức áp dụng những công nghệ và kỹ thuật, ứng dụng đi kèm của nó. Hãy điểm qua những gì được mong đợi sẽ diễn ra trong năm 2020.

Kubernetes đã không còn là một công nghệ mới và tên của nó đang lùi dần vào sau hậu trường. Sự tập trung sẽ được dành cho việc xây dựng các phương thức trừu tượng (abstractions) - để giảm độ phức tạp, công cụ và nền tảng bởi các cộng đồng đang không ngừng phát triển.

Dưới đây là 7 xu hướng đáng quan tâm trong năm 2020:

1. GitOps trở thành tiêu chuẩn cho Cloud Native

Một trong những xu hướng được mong chờ nhất trong năm 2019 là sự ra đời của GitOps. Là một phần mở rộng tự nhiên cho Cơ sở hạ tầng dưới dạng Mã (Infrastructure-as-Code) và Phân phối liên tục (Continuous Delivery). GitOps tập trung vào việc sử dụng Git làm cơ sở duy nhất (single source of truth) cho hệ thống. Thay đổi về cơ sở hạ tầng và ứng dụng được thực hiện bằng cách khai báo thông qua git repository (sau đây gọi tắt là git repo hoặc repo), với quy trình tự động đảm bảo trạng thái hiện tại của hệ thống phản ánh lại trạng thái trong repo. Thuật ngữ GitOps được đưa ra bởi Weave Works, bạn có thể đọc thêm qua blog của họ tại đây.

GitOps Engine là sản phẩm được tạo ra từ sự hợp tác giữa WeaWorks Flux và Intuit’s Argo, cho thấy tiềm năng tuyệt vời của công cụ tiêu chuẩn để thực hiện GitOps. Mong đợi có nhiều công cụ hơn sẽ tham gia hợp tác trong năm nay để có thể tham gia vào các dự án triệt để hơn.

GitOps đang ở giai đoạn đầu tiên được đón nhận bởi cộng đồng, nhưng được dự đoán sẽ trở thành một tiêu chuẩn cho tất cả các công ty có tham vọng hướng đến Cloud Native vào năm 2020.

2. Hybird Cloud là tương lai

Dù bạn có là fan của nó hay không, thì Hybrid hoặc Multi Cloud dường như sẽ là tương lai của các giải pháp Cloud Native. Trong tương lai, rõ ràng là không còn bất kỳ tổ chức lớn nào chạy hoàn toàn trên một cloud, cho dù cloud đó là on-premise, public hay private.

Vì nhiều lý do: bảo mật dữ liệu, phục hồi dữ liệu sau thảm họa (DR), quy mô xử lý, bảo mật dữ liệu cá nhân… giải pháp hybrid hoặc multi cloud sẽ được tin dùng hơn. Kết quả là, trong năm vừa qua, cả ba nhà cung cấp điện toán cloud lớn đã tung ra một sản phẩm để hỗ trợ hybrid cloud lai (AWS Outposts, Google’s Anthose, and Azure Arc).

Một trong những điểm hấp dẫn chính của Kubernetes đối với nhiều tổ chức là cách nó tự giới thiệu bản thân như một công cụ để thiết lập hybrid cloud. Mặc dù điều này đúng ở một mức độ nào đó, nhưng hỗ trợ nhiều cloud sẽ dẫn đến rất nhiều sự phức tạp. Có một số công cụ nhằm giúp đơn giản hóa việc này, Kubefed - còn gọi là Federation v2, Crossplane hoặc thông qua một lưới dịch vụ (service mesh) như Istio.

Trong năm tới, hy vọng cộng đồng và các công cụ sẽ tiếp tục phát triển, đồng thời các công ty đang tìm cách thực hiện các thiết lập hybrid cloud sẽ đánh giá lại kỳ vọng của họ khi họ nhận ra việc này tốn khá nhiều chi phí.

3. Kubernetes phải coi 2020 là năm của Developer

Một trong những lời chỉ trích lớn nhất về Kubernetes là nó không thân thiện với Developer. Đối với các nhóm quản trị (operations) và nền tảng (platforms), Kubernetes là một người hỗ trợ tuyệt vời. Nhưng thường thì các developer lại cảm thấy bị tụt hậu. Nó tạo thêm sự phức tạp trong vòng đời phần mềm của họ, họ phải học các công nghệ mới mà không có thêm nhiều lợi ích (có thể nhìn thấy). Có một môi trường phát triển giống như sản xuất vẫn còn rất khó khăn trong thế giới của các ứng dụng hướng đến Cloud Native, microservice và phân tán.

Ambassador, Draft, và Garden đang nỗ lực rất nhiều để giải quyết vấn đề này. Hy vọng năm 2020 sẽ là năm mà Kubernetes trở nên thân thiện hơn với các developer. Nhiều đội sẽ rời bỏ K8S nếu vấn đề này không được giải quyết.

4. SRE sẽ đi từ buzzword đến phổ biến

Kể từ khi Google phát hành ‘Site Reliability Engineering’ (Kỹ thuật ổn định hệ thống) lần đầu tiên và liệt kê chi tiết về cách thức vận hành các hệ thống sản xuất, thuật ngữ và vai trò đã tiếp tục phát triển nhanh chóng. Đến năm 2019, SRE vẫn đang rất phổ biến dựa trên các khảo sát gần đây.

Hầu hết các công ty đang triển khai SRE trong tổ chức của họ, nhưng một số lượng lớn trong số họ không áp dụng đúng quy trình và thay vào đó chỉ đơn giản là đổi thương hiệu cho các nhóm vận hành. Cuộc khảo sát tương tự từ Catchpoint, được liên kết ở trên, chỉ ra rằng SLO (Service Level Objectives - Mục tiêu cấp độ dịch vụ) thường không được xác định và vẫn còn quá nhiều vấn đề trong tổ chức - hai số liệu chính của SRE.

Với thực tiễn đang tiếp tục trưởng thành và phổ biến hơn, các quy trình sẽ trở nên nghiêm ngặt hơn. Bao gồm đánh giá sản xuất kỹ lưỡng cho tất cả các dịch vụ và SLO/SLI/SLA được xác định rõ, và để SRE thích hợp trở thành một yêu cầu khắt khe đối với bất kỳ công ty nào duy trì hệ thống sản xuất.

5. ’Remote first’ sẽ cung cấp cho các công ty nhiều lợi thế hơn

Làm việc từ xa không chỉ là mong muốn của người lao động, mà nó còn buộc tạo ra các thực tiễn tốt nhất về mặt giao tiếp và chủ động. (Dưới 32% những người tham gia khảo sát developer hàng năm của Stack Overflow vào năm 2019 cho biết cơ hội làm việc từ xa là quan trọng nhất đối với họ khi việc lựa chọn công việc.)

Các công cụ và thực tiễn được yêu cầu để hỗ trợ công việc từ xa có lợi bất kể tổ chức đó có nhân viên làm việc từ xa hay không.

Điều này có liên quan gì với Cloud Native? Cloud Native không chỉ là về công nghệ. Từ góc độ của Luật Conway, nếu chúng ta muốn xây dựng các hệ thống phân tán quy mô lớn với các giao diện khai báo rõ ràng, chúng ta nên xem xét để thực hiện những điều tương tự với cấu trúc tổ chức của mình.

Với việc thúc đẩy công việc từ xa tiếp tục, các công ty cung cấp phương pháp làm việc từ xa có hy vọng sẽ có lợi thế đáng kể so với các đối thủ cạnh tranh.

6. MLOps mở ra những cơ hội mới

Mặc dù không nhất thiết phải triển khai theo hướng Cloud Native, nhưng việc giới thiệu MLOps vào năm 2019 là một sự phát triển thú vị. MLOps là quá trình vận hành và quản lý vòng đời của machine learning trong sản xuất, đặc biệt là áp dụng các công cụ và thực tiễn của DevOps cho lĩnh vực khoa học dữ liệu.

Có thể coi đây là cầu nối giữa machine learning và Cloud Native, vì nó cho phép các nhóm khoa học dữ liệu và ML tận dụng các thực tiễn và công nghệ của Cloud Native. Cơ hội ở đây là rất lớn, và mong đợi lĩnh vực này sẽ thực sự bùng nổ trong năm tới.

7. Tranh luận về đạo đức sẽ ngày càng lớn hơn và cấp bách hơn

Trong vài năm qua, những lo ngại về đạo đức và công nghệ đã trở thành tâm điểm, từ việc các công ty sử dụng dữ liệu cho đến vấn đề tiêu thụ năng lượng của các trung tâm dữ liệu.

Đây đều là những nội dung quan trọng. Từ góc độ Cloud Native, sẽ có nhiều cuộc thảo luận hơn vào năm 2020 về việc làm thế nào để giúp giảm lượng khí thải carbon và nhiều nội dung khác nữa.

Phần kết luận

Trong khi bản thân công nghệ Cloud Native ngày càng trở nên chủ đạo, không gian chỉ phát triển nhanh hơn. Việc áp dụng các công nghệ chính như Kubernetes tiếp tục mở rộng, dẫn đến nhu cầu trừu tượng hóa và công cụ bổ sung.

Đây là một vài trong số các nội dung đáng chú ý trong năm nay, nhưng các lĩnh vực chưa được khám phá chắc chắn sẽ phát sinh vào năm 2020 mới là điều hấp dẫn hơn. Nguồn: https://blog.container-solutions.com/

· Một phút để đọc
ManhPT

Lịch sử git thiếu nhất quán

Hầu hết developer chúng ta đều biết đến git - nếu chưa biết thì phải tìm hiểu và sử dụng ngay - một công cụ quá tuyệt vời để quản lý source code. Và giống như việc đặt tên biến trong code, commit messages cũng là một thứ gì đó thực sự gây đau đầu.

Trong một team, có anh em sẽ chỉ đặt một message ngắn ngủn cho xong, một số cẩn thận sẽ viết rõ những thay đổi trong đó và chèn thêm cả JIRA ticket number. Như thế sẽ tạo ra sự thiếu nhất quán trong lịch sử commit vốn đã rất phức tạp. Điều này khiến mình nghĩ đến việc chuẩn hóa commit trong project hiện tại.

Lựa chọn công cụ

Để có một commit có đầy đủ ý nghĩa với: loại commit (feature, fix bug, refactor...), JIRA ticket number, description. Sau thời gian ngâm cứu trên mạng thì mình đã tìm ra Commitizen và quyết định sử dụng nó để áp chuẩn cho việc commit.

Commitizen là công cụ dạng command line (dòng lệnh) hỗ trợ tự động format commit messages bằng cách hỏi bạn một vài câu hỏi, bạn nhập câu trả lời và commitizen sẽ tạo commit theo chuẩn dựa trên các thông tin được nhập. Bạn có thể cài đặt commitizen global với:

npm install commitizen -g

Không thích cài global thì có thể cài vào dev dependencies của package.json cũng ok:

npm install commitizen --save-dev

Giờ thì thay vì commit bằng lệnh:

git commit

Ta dùng:

git cz

Cấu hình commitizen

Để bắt đầu làm việc với commitizen, chúng ta cần cài đặt thêm một vài cấu hình có sẵn trong package.json gọi là adapter. Những adapter này sẽ định nghĩa những câu hỏi khi commit. Bạn có thể chọn một adapter từ đây.

Trong bài viết này mình chọn cz-conventional-changelog để bắt đầu, bạn cũng nên cài nó vào dev dependencies.

npm install cz-conventional-changelog --save-dev

Tiếp tục cấu hình adapter với lệnh sau:

commitizen init cz-conventional-changelog --save-dev

cz-conventional-changelog sẽ ép commit message theo chuẩn như sau:

type(scope): JIRA-Ticket - Short description

Sau khi gõ lệnh "git cz", dòng lệnh sẽ đưa ra những câu hỏi về: type, scope, short description, long description, breaking changes - vui lòng đọc kỹ các câu hỏi trước khi chọn hoặc trả lời, việc này khá dễ dàng và sẽ rất nhanh quen thôi.

Cấu hình validate commit message

Adapter cz-conventional-changelog không yêu cầu nhập JIRA ticket number nên chúng ta cần kiểm tra dòng đầu của commit message để chắc chắn nó có chưa JIRA ticket number. Ta có thể làm điều này với Huskyvalidate-commit-message. Để bắt đầu thì cũng cài 2 tool này dạng dev dependencies:

npm install husky --save-dev
npm install validate-commit-msg --save-dev

Husky là một tool cho phép ta có thể chạy kèm lệnh bất kỳ với git hooks, còn validate-commit-message thì sử dụng regex kiểm tra string. Để cấu hình 2 tool này thì chúng ta cần thêm thủ công đoạn config sau vào bên dưới "config" trong package.json:

"validate-commit-msg": {
"types": [
"feat",
"fix",
"docs",
"style",
"refactor",
"perf",
"test",
"chore",
"revert"
],
"warnOnFail": false,
"maxSubjectLength": 72,
"subjectPattern": "^[A-Z]+-[0-9]+ - .*",
"subjectPatternErrorMsg": "Subject must be in format 'CMS-123 - Commit message'",
"helpMessage": ""
}

Commit theo chuẩn không chỉ cho đẹp

Ngoài cải thiện tính dễ dễ hiểu của commit messages. Việc commit theo chuẩn chung như trên còn có rất nhiều lợi ích khác:

  • Quan trọng nhất phải kể đến đó là có thể đánh version phần mềm dựa trên commit (theo https://semver.org/)
  • Trigger thay đổi trên các tool dự án (JIRA)
  • CICD support
  • ...

Tận hưởng kết quả

Done rồi, commitizen đã sẵn sàng để bảo vệ sự trong sáng và nhất quán trong lịch sử git của bạn. Bài viết dựa trên kinh nghiệm cá nhân và có sự tham khảo + dịch lại từ: https://dev.bleacherreport.com/how-we-use-commitizen-to-clean-up-commit-messages-a16790dcd2fd.

· Một phút để đọc
ManhPT

Why docker swarm? Liên quan gì đến gitlab-runner?

Setup gitlab-runner trên môi trường docker bình thường khá đơn giản trong bài viết này. Nhưng nếu bạn có nhiều máy (máy tính local hoặc server) thì sao? Setup gitlab-runner cho từng máy không phải là một ý hay:

Kết hợp các máy này lại với nhau, tạo thành một cụm docker swarm.

Điều kiện cần

Docker swarm

Có lẽ bạn đã có sẵn môi trường docker swarm trước khi tìm thấy bài viết này. Còn nếu chưa thì bạn vui lòng tham khảo:

Tokens

Bạn vui lòng google hoặc tham khảo nội dung swarm.yml bên dưới để biết cách lấy token.

  • Gitlab runner registration token (có thể lấy của từng project hoặc group)
  • Gitlab personal access token (tại đây)

Deploy stack gitlab-runner

Tạo một file swarm.yml với nội dung như sau:

version: '3.7'

secrets:

# Find your registration token at: "Your project" > "Settings" > "CI/CD" > "Runners settings" > "Specific Runners" (look for registration token)
# Register it as `GITLAB_REGISTRATION_TOKEN`: `docker secret create GITLAB_REGISTRATION_TOKEN YOUR_REGISTRATION_TOKEN`
GITLAB_REGISTRATION_TOKEN:
external: true
# Find your personal access token at: "Your user account" > "Settings" > "Access Tokens" > "Create personal access token" (for api)
# Register it as `GITLAB_PERSONAL_ACCESS_TOKEN`: `docker secret create GITLAB_PERSONAL_ACCESS_TOKEN <YOUR ACCESS TOKEN>`
GITLAB_PERSONAL_ACCESS_TOKEN:
external: true

services:

# Gitlab Runner - https://gitlab.com/gitlab-org/gitlab-runner
runner:
image: gitlab/gitlab-runner:latest
environment:
- CONCURRENT=8
- REGISTER_LOCKED=1
- REGISTER_NON_INTERACTIVE=1
- RUNNER_EXECUTOR=docker
- DOCKER_IMAGE=docker
- DOCKER_VOLUMES=/var/run/docker.sock:/var/run/docker.sock
- RUNNER_NAME=docker
- API_URL=https://gitlab.com/api/v4
- CI_SERVER_URL=https://gitlab.com/ci
entrypoint: "bash"
secrets:
- GITLAB_REGISTRATION_TOKEN
command: |
-c '
set -e
printf "Setting configuration...\\n"
export REGISTRATION_TOKEN="$$(cat /run/secrets/GITLAB_REGISTRATION_TOKEN)"
sed -i "s/^concurrent = .*/concurrent = $${CONCURRENT}/" /etc/gitlab-runner/config.toml
printf "\\n"
printf "Registering runner...\\n"
gitlab-runner register --non-interactive
printf "\\n"
printf "List runners...\\n"
gitlab-runner list
printf "\\n"
printf "Running runner...\\n"
gitlab-runner run --user=gitlab-runner --working-directory=/home/gitlab-runner
'
volumes:
- /var/run/docker.sock:/var/run/docker.sock
deploy:
mode: global
placement:
constraints:
- node.role == manager
labels:
- "traefik.enable=false"
healthcheck:
test: ["CMD-SHELL", "gitlab-runner verify --name docker 2>&1 | grep --quiet \"is alive\""]
start_period: 10s
interval: 10s
timeout: 10s
retries: 10

# Gitlab Manager to unregister GitLab Runners
manager:
image: alpine:latest
environment:
- API_URL=https://gitlab.com/api/v4
- CI_SERVER_URL=https://gitlab.com/ci
secrets:
- GITLAB_PERSONAL_ACCESS_TOKEN
entrypoint: sh
command: |
-c '
set -e
printf "Installing dependencies...\\n"
apk --no-cache add curl jq
printf "\\n"
export PERSONAL_ACCESS_TOKEN="$$(cat /run/secrets/GITLAB_PERSONAL_ACCESS_TOKEN)"
while true; do
printf "Checking runners...\\n"
curl -sS --header "PRIVATE-TOKEN: $${PERSONAL_ACCESS_TOKEN}" "$${API_URL}/runners?per_page=100" | \
jq -c ".[] | select(false==.is_shared) | select(\"online\"==.status) | .id" | \
while read RUNNER_ID; do
printf "Runner $${RUNNER_ID} is online\\n"
done
curl -sS --header "PRIVATE-TOKEN: $${PERSONAL_ACCESS_TOKEN}" "$${API_URL}/runners?per_page=100" | \
jq -c ".[] | select(false==.is_shared) | select(\"online\"!=.status) | .id" | \
while read RUNNER_ID; do
printf "Deleting runner $${RUNNER_ID}...\\n"
curl -sS --request DELETE --header "PRIVATE-TOKEN: $${PERSONAL_ACCESS_TOKEN}" "$${API_URL}/runners/$${RUNNER_ID}"
done
printf "All offline runners deleted\\n"
printf "Waiting for 24 hours...\\n"
sleep 24h
done
printf "\\n"
'
deploy:
labels:
- "traefik.enable=false"
healthcheck:
test: ["CMD-SHELL", "command -v curl"]
start_period: 10s
interval: 10s
timeout: 10s
retries: 10

# Gitlab Runner Docker Cleanup - https://gitlab.com/gitlab-org/gitlab-runner-docker-cleanup
cleaner:
image: quay.io/gitlab/gitlab-runner-docker-cleanup
environment:
- CHECK_PATH=/data
- LOW_FREE_SPACE=10G
- EXPECTED_FREE_SPACE=20G
- LOW_FREE_FILES_COUNT=1048576
- EXPECTED_FREE_FILES_COUNT=2097152
- USE_DF=1
- CHECK_INTERVAL=10s
- RETRY_INTERVAL=30s
- DEFAULT_TTL=60m
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- cleaner_data:/data
deploy:
restart_policy:
condition: any
labels:
- "traefik.enable=false"

volumes:
cleaner_data:

Deploy stack này:

docker stack deploy -c swarm.yml runner

Xong rồi đó! Nếu không one hit lên luôn thì tự google nhé =)).

· Một phút để đọc
ManhPT

Vấn đề là...

Nếu bạn đã từng sử dụng git trên "cửa sổ dòng lệnh" (terminal) của windows, linux hay macOS, bạn sẽ thấy rằng mật khẩu git của chúng ta được lưu lại tự động. Sau đó, chúng ta chỉ cần fetch - push - pull bình thường. Không cần nhập lại username và password của git nữa.

Hơi tiếc là Ubuntu nói riêng và linux nói chung không có tính năng này. Dĩ nhiên chúng ta có thể cài đặt thêm phần mềm bên thứ 3 để có được tính năng tương tự. Mmình chưa thử và cũng ko tin tưởng để thử... lol.

Giải pháp

Sau đây là một thủ thuật nhỏ và cực kỳ đơn giản để bạn có thể quên đi việc bị hỏi username và password liên tục mỗi khi git fetch. Đó là sử dụng git credential storage chỉ với một câu lệnh duy nhất.

git config --global credential.helper store
  • store mode: chế độ này lưu thông tin đăng nhập của bạn dưới dạng plain-text mặc định trong file ~/.my-credentials. Bạn sẽ chỉ phải nhập lại mật khẩu khi bạn đã thay đổi mật khẩu trên git server. Cách này không được bảo mật cho lắm vì mật khẩu được lưu cứng dưới dạng không mã hoá. Do đó, ít nhất các bạn cũng nên sử dụng personal access token thay cho mật khẩu, ví dụ: github personal access token, gitlab personal access token... (lúc nào mà nhỡ có bị lộ thì revoke cái là xong).
git config --global credential.helper cache
git config --global credential.helper cache '--timeout 30000'
  • cache mode: chế độ này thì an toàn hơn do mật khẩu của bạn sẽ được lưu trong RAM thay vì file cứng và dĩ nhiên là có timeout - mặc định là 15 phút (900 giây). Bạn có thể tuỳ ý thay đổi thời gian timeout sao cho phù hợp với nhu cầu. Mình khuyến cáo nên sử dụng cách này.

Kết luận

Trong thực tế, việc sử dụng private key vẫn tối ưu và bảo mật hơn so với trực tiếp lưu trữ mật khẩu, nhưng việc setup không đơn giản như trên. Các đồng dâm tuỳ ý chọn lựa nhé.

· Một phút để đọc
ManhPT

Vấn đề là...

Có nhiều lúc bạn cần sử dụng một phiên bản nhất định của Java để phục vụ công việc, ví dụ như build app android thì cần Java 8 trong khi version mới nhất của Java hiện đã là 11 (tại thời điểm viết bài).

Sau đây là một vài bước đơn giản để bạn có thể thiết lập môi trường MacOS sử dụng một phiên bản nhất định (trong trường hợp máy bạn cài đặt nhiều phiên bản Java) và thay đổi giữa các phiên bản của Java.

Bạn không cần phải cài đặt thêm bất cứ plugin hay thư viện nào để có thể thực hiện các bước sau đây.

1. Đầu tiên bạn cần list ra tất cả các version Java hiện có trên máy bằng câu lệnh sau:

/usr/libexec/java_home -V

Bạn có thể sẽ nhận được nội dung như sau:

Matching Java Virtual Machines (3):
1.8.0_202, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_05.jdk/Contents/Home
1.6.0_65-b14-462, x86_64: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
1.6.0_65-b14-462, i386: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home

/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home

2. Chọn version mà bạn muốn chọn làm mặc định

Ví dụ tôi chọn version 1.6.0_65-b14-462 làm mặc định thì chỉ cần:

export JAVA_HOME=$(/usr/libexec/java_home -v 1.6.0_65-b14-462)

Bạn cũng có thể đặt câu lệnh này vào .bashrc hoặc .zshrc của bạn để auto exec mỗi khi bạn mở một shell session mới.

3. Kiểm tra lại với java -version bạn sẽ nhận được thông tin tương ứng

java version "1.6.0_65"
Java(TM) SE Runtime Environment (build 1.6.0_65-b14-462-11M4609)
Java HotSpot(TM) 64-Bit Server VM (build 20.65-b04-462, mixed mode)

Bonus:

Bạn còn có thể:

export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)

hoặc

    
export JAVA_HOME=$(/usr/libexec/java_home -v 1.6)

Thiết lập như thế này sẽ hỗ trợ chọn version linh hoạt hơn. Đồng thời vẫn đảm bảo khả năng tương thích trong cùng một phiên bản Java.

· Một phút để đọc
ManhPT

Việc cài đặt gitlab-runner sử dụng docker được hướng dẫn khá đầy đủ tại tài liệu chính thống. Nhưng thực tế quá trình cài đặt và sử dụng thường không diễn ra suôn sẻ với mình lắm nên mình chắc nhiều bạn cũng gặp vấn đề giống mình. Bài viết này chủ yếu chỉ ra những điều cần chú ý khi bạn cài đặt và sau khi cài thành công mà pipeline có thể vẫn báo tình trạng stuck (job không thể kích hoạt bởi gitlab-runner).

Triển khai gitlab-runner

Để cài đặt gitlab-runner bạn chỉ cần 2 câu lệnh sau là đủ:

1. Cài đặt gitlab-runner

sudo docker run -d --name gitlab-runner --restart always \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
-v /var/run/docker.sock:/var/run/docker.sock \
gitlab/gitlab-runner:latest

2. Cấu hình gitlab-runner

sudo docker run --rm -t -i \
-v /srv/gitlab-runner/config:/etc/gitlab-runner \
gitlab/gitlab-runner register

Để điền thông tin cấu hình bạn chỉ cần theo sát hướng dẫn tại đây. Vậy là xong rồi!

Chú ý

  • Cài đặt xong rồi nhưng pipeline của tôi vẫn không được kích hoạt? - Rất có thể bạn cần cấu hình thêm một chút để Runners có thể kích hoạt các jobs không được tags, việc này có thể làm ngay trên giao diện web gitlab. (Link tham khảo)
  • Tôi cần build docker image trên CI nhưng khi chạy thì báo không tìm thấy docker? - Chắc là quên bật --privileged (link tham khảo).
  • Nếu bạn muốn sử dụng gitlab-runner cho docker swarm thì có thể tham khảo tại đây.

· Một phút để đọc
ManhPT

Bạn có bao giờ tự hỏi

  1. Git còn gì ngoài git commit, git pushgit pull? Thỉnh thoảng dùng thêm git merge, còn gì nữa không?
  2. git mergegit rebase khác gì nhau, nên dùng cái nào?
  3. Ở vị trí team leader bạn sẽ vận hành git ra sao để kết hợp với process của team (agile) và giải quyết các conflict trong quá trình code?
  4. Lịch sử git có giá trị như thế nào? Hay bạn chẳng bao giờ để ý đến nó?

Nếu bạn là 1 git command line master thì mọi thứ đều có thể được giải quyết dưới local bằng dòng lệnh. Nhưng khi làm việc trong một nhóm đông thành viên, làm thế nào để xử lý các vấn đề conflict code, release ra sao, thêm feature mới như thế nào, hotfix ra làm sao một cách trơn tru và hiệu quả, giảm thiểu tối đa các bước thủ công, tiến dần đến một git workflow tự động hoàn toàn (devops).

Luôn luôn tạo ra linear history

Git Workflow được giới thiệu sau đây luôn giữ một tư duy cực kỳ nhất quán về git history luôn luôn là linear history (có thể hiểu là history trên một đường thẳng). Nhìn trong hình đủ thấy linear history dễ hiểu hơn rất nhiều so với non-linear history, đủ dễ để nhìn vào graph là có thể thấy được thứ tự của các commit và sự khác nhau giữa các version được release.

Tham khảo

  1. http://www.bitsnbites.eu/a-tidy-linear-git-history/

git mergegit rebase đúng lúc đúng chỗ

Nguyên tắc tiên quyết

  1. Để update code mới nhất, không merge trên local, hãy dùng rebase
  2. merge tự động bằng merge (pull) request (cần cấu hình để khi merge sẽ sinh ra một empty commit nhằm đánh dấu vị trí merge)

Một ví dụ thực tế về linear history