# 실습

### ClusterIP

1. Deployment 생성&#x20;

   ```
   cat <<'EOF' | kubectl apply -f -
   apiVersion: apps/v1
   kind: Deployment
   metadata:
     name: nginx
   spec:
     replicas: 3
     selector:
       matchLabels:
         app: nginx
     template:
       metadata:
         labels:
           app: nginx
       spec:
         containers:
         - name: nginx
           image: nginx
           ports:
           - containerPort: 80
           volumeMounts:
           - name: html
             mountPath: /usr/share/nginx/html
         initContainers:
         - name: index
           image: curlimages/curl
           command:
           - "sh"
           - "-c"
           - "echo 'hello from $(POD_NAME), my ip is $(POD_IP)' > /data/index.html"
           volumeMounts:
           - name: html
             mountPath: /data
           env:
           - name: POD_NAME
             valueFrom:
               fieldRef:
                 fieldPath: metadata.name
           - name: POD_IP
             valueFrom:
               fieldRef:
                 fieldPath: status.podIP
         volumes:
         - name: html
           emptyDir: {}
   EOF
   ```
2. Service 생성 &#x20;

   ```
   kubectl expose deployment nginx --port 80
   ```
3. 생성된 Service 확인&#x20;

   ```
   kubectl get svc nginx -o wide
   ```
4. 생성된 Endpoint 확인&#x20;

   ```
   kubectl get ep nginx
   ```
5. 생성된 Pod의 IP주소 확인 &#x20;

   ```
   kubectl get pod -l app=nginx -o wide
   ```
6. Endpoint에 타겟으로 등록되어 있는 Pod 목록 확인

   ```
   kubectl get ep nginx \
   -o jsonpath='{range .subsets[*].addresses[*]}{.targetRef.name}{"\t"}{.ip}{"\n"}{end}'
   ```
7. 생성된 Deployment의 Replica 갯수를 6개로 조정&#x20;

   ```
   kubectl scale deployment nginx --replicas=6
   ```
8. 생성된 Pod의 IP주소 확인 &#x20;

   ```
   kubectl get pod -l app=nginx -o wide
   ```
9. Endpoint에 타겟으로 등록되어 있는 Pod 목록 확인

   ```
   kubectl get ep nginx \
   -o jsonpath='{range .subsets[*].addresses[*]}{.targetRef.name}{"\t"}{.ip}{"\n"}{end}'
   ```
10. Pod 생성&#x20;

    ```
    kubectl run curl --image=nginx -- sleep 3600
    ```
11. 위에서 생성한 Pod에서 Service 호출&#x20;

    ```
    kubectl exec curl -- \
    bash -c "for i in {1..20};do curl -s $(kubectl get svc nginx -o=jsonpath='{.spec.clusterIP}');done"
    ```
12. 새로운 터미널을 열고 kube-proxy 로그 확인 - *아래의 명령어를 입력하고 엔터키를 몇번 입력해서 간격을 만들어두면 새로운 로그를 좀 더 쉽게 알아볼수 있음*

    ```
    kubectl -n kube-system logs ds/kube-proxy -f
    ```
13. 기존 터미널로 돌아와서 생성된 Deployment의 Replica 갯수를 3개로 조정&#x20;

    ```
    kubectl scale deployment nginx --replicas=3
    ```
14. 다른 터미널로 이동해서 kube-proxy 로그 확인&#x20;
15. 새로운 터미널을 열고 한개의 Node로 Session Manager 연결

    ```
    aws ssm start-session --target \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
    ```
16. Iptable의 모든 규칙 확인&#x20;

    ```
    sudo iptables-save
    ```
17. Iptable의 NAT 규칙 확인

    ```
    sudo iptables -L -t nat
    ```
18. KUBE-SERVICES 규칙 확인&#x20;

    ```
    sudo iptables -t nat -L KUBE-SERVICES -n  | column -t
    ```
19. 생성된 Service의 Cluster IP로 연결된 규칙 값을 환경변수로 저장

    ```
    export SERVICE_CHAIN=$(sudo iptables -t nat -L KUBE-SERVICES -n  | column -t | grep "default/nginx" | grep -oE "^KUBE-SVC-[A-Z0-9]+")
    echo $SERVICE_CHAIN
    ```
20. Service의 Cluster IP로 연결된 규칙의 상세내용 확인

    ```
    sudo iptables -t nat -L $SERVICE_CHAIN -n  | column -t
    ```
21. 위의 명령어로 나온 결과중의 한개의 Chain 규칙 확인&#x20;

    ```
    sudo iptables -t nat -L $(sudo iptables -t nat -L $SERVICE_CHAIN -n  | column -t | grep -oE "^KUBE-SEP-[A-Z0-9]+" | head -1) \
    -n  | column -t
    ```
22. 첫번째 터미널로 이동해서 생성된 Pod의 IP주소 확인 &#x20;

    ```
    kubectl get pod -o wide -l app=nginx
    ```
23. 생성된 Deployment의 Replica 갯수를 6개로 조정&#x20;

    ```
    kubectl scale deployment nginx --replicas=6
    ```
24. 두번째 터미널에서 kube-proxy 로그 확인&#x20;
25. 세번째 터미널로 이동해서 20번 명령어 재실행&#x20;
26. 첫번째 터미널로 이동해서 CoreDNS 설정 파일 확인&#x20;

    ```
    kubectl -n kube-system get cm coredns -o yaml | yq e '.data' -
    ```
27. log 플러그인 활성화 - [https://coredns.io/plugins/log](https://coredns.io/plugins/log/)

    ```
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: coredns
      namespace: kube-system
      labels:
        eks.amazonaws.com/component: coredns
        k8s-app: kube-dns
    data:
      Corefile: |
        .:53 {
            errors
            health
            kubernetes cluster.local in-addr.arpa ip6.arpa {
              pods insecure
              fallthrough in-addr.arpa ip6.arpa
            }
            prometheus :9153
            forward . /etc/resolv.conf
            cache 30
            loop
            reload
            loadbalance
            log
        }
    EOF
    ```
28. CoreDNS Pod 재배포&#x20;

    ```
    {
        kubectl -n kube-system scale deployment coredns --replicas=0
        sleep 60
        kubectl -n kube-system scale deployment coredns --replicas=2
        sleep 10
        kubectl -n kube-system get pod -l k8s-app=kube-dns
    }
    ```
29. 두번째 터미널에서 CoreDNS 로그 확인&#x20;

    ```
    kubectl -n kube-system logs deploy/coredns -f
    ```
30. 첫번째 터미널로 이동해서 Pod안에 설정된 DNS 설정 파일 확인&#x20;

    ```
    kubectl exec curl -- cat /etc/resolv.conf
    ```
31. CoreDNS 주소 확인

    ```
    kubectl -n kube-system get svc kube-dns
    ```
32. CURL 명령어로 Service 이름 호출&#x20;

    ```
    kubectl exec curl -- curl -s nginx
    ```
33. 두번째 터미널에서 CoreDNS 로그 확인 - 새로운 로그 출력되지 않으면 32번 명령어를 다시 수행
34. 첫번째 터미널로 이동해서 새로운 Namespace 생성&#x20;

    ```
    kubectl create ns web
    ```
35. 생성한 Namespace 안에 Deployment 생성&#x20;

    ```
    kubectl -n web create deployment httpd --image=httpd --port=80
    ```
36. Service 생성 &#x20;

    ```
    kubectl -n web expose deployment httpd
    ```
37. CURL 명령어로 Service 이름 호출 &#x20;

    ```
    kubectl exec curl -- curl -s httpd
    ```
38. 두번째 터미널에서 CoreDNS 로그 확인 - 새로운 로그 출력되지 않으면 37번 명령어를 다시 수행
39. CURL 명령어로 Service 호출 -  service.namespace

    ```
    kubectl exec curl -- curl -s httpd.web
    ```
40. CURL 명령어로 Service 호출 -  service.namespace.svc

    ```
    kubectl exec curl -- curl -s httpd.web.svc
    ```
41. CURL 명령어로 Service 호출 -  service.namespace.svc.cluster

    ```
    kubectl exec curl -- curl -s httpd.web.svc.cluster
    ```
42. CURL 명령어로 Service 호출 -  FQDN

    ```
    kubectl exec curl -- curl -s httpd.web.svc.cluster.local
    ```
43. 생성한 리소스 삭제&#x20;

    ```
    {
        kubectl delete ns web
        kubectl delete pod curl
        kubectl delete svc nginx
        kubectl delete deploy nginx
    }
    ```

### NodePort

1. Deployment 생성&#x20;

   ```
   kubectl create deployment nginx --image=nginx --port=80 --replicas=3
   ```
2. Service 생성 &#x20;

   ```
   kubectl expose deployment nginx --type=NodePort
   ```
3. 생성된 Service 확인&#x20;

   ```
   kubectl get svc nginx -o wide
   ```
4. Node의 공인 IP 주소 확인&#x20;

   ```
   kubectl get node -o wide
   ```
5. 웹 브라우저를 열고 NODE\_EXTERNAL\_IP:NODEPORT 주소로 접속 시도 - *아래의 명령어로 주소 확인 가능*&#x20;

   ```
   echo $(kubectl get node -o=jsonpath='{.items[0].status.addresses[?(@.type=="ExternalIP")].address}')\
   :$(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}')
   ```
6. 접속이 안될 경우에는 Node의 보안그룹 확인

   ```
   aws ec2 describe-security-groups --group-ids \
   $(aws ec2 describe-instances --instance-ids \
   $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \
   --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \
   --query "SecurityGroups[*].IpPermissions"
   ```
7. 보안그룹에 Service에 명시된 포트에 대한 인바운드 규칙이 없을 경우에 아래의 명령어로 규칙 추가

   ```
   aws ec2 authorize-security-group-ingress --group-id \
   $(aws ec2 describe-instances --instance-ids \
   $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \
   --query 'Reservations[0].Instances[0].SecurityGroups[0].GroupId' --output text) \
   --protocol tcp \
   --port $(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}') \
   --cidr 0.0.0.0/0
   ```
8. 보안그룹에 인바운드 규칙이 추가되었는지 확인

   ```
   aws ec2 describe-security-groups --group-ids \
   $(aws ec2 describe-instances --instance-ids \
   $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \
   --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \
   --query "SecurityGroups[*].IpPermissions"
   ```
9. 웹 브라우저를 열고 NODE\_EXTERNAL\_IP:NODEPORT 주소로 접속 시도 - *아래의 명령어로 주소 확인 가능*&#x20;

   ```
   echo $(kubectl get node -o=jsonpath='{.items[0].status.addresses[?(@.type=="ExternalIP")].address}')\
   :$(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}')
   ```
10. 새로운 터미널을 열고 한개의 Node로 Session Manager 연결

    ```
    aws ssm start-session --target \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
    ```
11. Iptable의 모든 규칙 확인&#x20;

    ```
    sudo iptables-save
    ```
12. KUBE-SERVICES 규칙 확인&#x20;

    ```
    sudo iptables -t nat -L KUBE-SERVICES -n  | column -t
    ```
13. KUBE-NODEPORTS 규칙 확인&#x20;

    ```
    sudo iptables -t nat -L KUBE-NODEPORTS -n  | column -t
    ```
14. 생성된 Service의 NodePort로 연결된 규칙 값을 환경변수로 저장

    ```
    export NODEPORT_CHAIN=$(sudo iptables -t nat -L KUBE-NODEPORTS -n  | column -t | grep "default/nginx" | grep -oE "^KUBE-SVC-[A-Z0-9]+")
    echo $NODEPORT_CHAIN
    ```
15. KUBE-SERVICES 규칙 중에서 NodePort로 연결된 규칙 확인

    ```
    sudo iptables -t nat -L KUBE-SERVICES -n  | column -t | grep $NODEPORT_CHAIN
    ```
16. 첫번째 터미널로 이동해서 Service의 Cluster IP 확인

    ```
    kubectl get svc nginx
    ```
17. 다른 터미널로 이동해서 NodePort로 연결된 규칙의 상세내용 확인

    ```
    sudo iptables -t nat -L $NODEPORT_CHAIN -n  | column -t
    ```
18. 위의 명령어로 나온 결과중의 한개의 Chain 규칙 확인&#x20;

    ```
    sudo iptables -t nat -L \
    $(sudo iptables -t nat -L $NODEPORT_CHAIN -n  | column -t | grep -oE "^KUBE-SEP-[A-Z0-9]+" | head -1) \
    -n  | column -t
    ```
19. 첫번째 터미널로 이동해서 생성된 Pod의 IP주소 확인 &#x20;

    ```
    kubectl get pod -o wide -l app=nginx
    ```
20. 다른 터미널로 이동해서 Node에 열려있는 포트 정보 확인&#x20;

    ```
    sudo netstat -tlnp
    ```
21. CURL 명령어로 Service 호출&#x20;

    ```
    curl localhost:NODEPORT
    ```
22. 첫번째 터미널로 이동해서 보안그룹에 추가한 인바운드 규칙 삭제

    ```
    aws ec2 revoke-security-group-ingress --group-id \
    $(aws ec2 describe-instances --instance-ids \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \
    --query 'Reservations[0].Instances[0].SecurityGroups[0].GroupId' --output text) \
    --protocol tcp \
    --port $(kubectl get svc nginx -o=jsonpath='{.spec.ports[0].nodePort}') \
    --cidr 0.0.0.0/0
    ```
23. 인바운드 규칙이 삭제되었는지 확인

    ```
    aws ec2 describe-security-groups --group-ids \
    $(aws ec2 describe-instances --instance-ids \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \
    --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \
    --query "SecurityGroups[*].IpPermissions"
    ```
24. 생성한 리소스 삭제&#x20;

    ```
    {
        kubectl delete deploy nginx
        kubectl delete svc nginx
    }
    ```

### LoadBalancer

1. Deployment 생성&#x20;

   ```
   kubectl create deployment nginx --image=nginx --port=80 --replicas=3
   ```
2. Service 생성 &#x20;

   ```
   kubectl expose deployment nginx --type=LoadBalancer
   ```
3. 생성된 Service 확인&#x20;

   ```
   kubectl get svc nginx -o wide
   ```
4. 생성된 Service 객체에 발생한 Event 확인

   ```
   kubectl describe svc nginx
   ```
5. 웹 브라우저를 열고 Service의 External IP 주소로 접속 - *아래의 명령어로 주소 확인 가능*

   ```
   kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}{"\n"}' 
   ```
6. 생성된 Service 상세 내용 확인&#x20;

   ```
   kubectl get svc nginx -o=jsonpath='{.spec}' | jq
   ```
7. 생성된 ELB 이름 확인&#x20;

   ```
   kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' 
   ```
8. ELB 상세 내용 확인 &#x20;

   ```
   aws elb describe-load-balancers --load-balancer-names \
   $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' )
   ```
9. ELB의 Listener 설정 확인

   ```
   aws elb describe-load-balancers --load-balancer-names \
   $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' ) \
   --query 'LoadBalancerDescriptions[*].ListenerDescriptions'
   ```
10. ELB의 보안그룹 확인

    ```
    aws elb describe-load-balancers --load-balancer-names \
    $(kubectl get svc nginx -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' | grep -o -E '^[a-z0-9]+' ) \
    --query 'LoadBalancerDescriptions[*].SecurityGroups'
    ```
11. 노드에 부여된 보안그룹에 ELB 보안그룹에 대한 새로운 인바운드 규칙이 추가 됐는지 확인&#x20;

    ```
    aws ec2 describe-security-groups --group-ids \
    $(aws ec2 describe-instances --instance-ids \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+") \
    --query 'Reservations[0].Instances[0].SecurityGroups[*].GroupId' --output text) \
    --query "SecurityGroups[*].IpPermissions"
    ```
12. 새로운 터미널을 열고 한개의 Node로 Session Manager 연결

    ```
    aws ssm start-session --target \
    $(kubectl get node -o jsonpath='{.items[0].spec.providerID}{"\n"}' | grep -oE "i-[a-z0-9]+")
    ```
13. KUBE-NODEPORTS 규칙 확인&#x20;

    ```
    sudo iptables -t nat -L KUBE-NODEPORTS -n  | column -t
    ```
14. 첫번째 터미널로 이동해서 생성한 리소스 삭제&#x20;

    ```
    {
        kubectl delete deploy nginx
        kubectl delete svc nginx
    }
    ```

### Network Load Balancer

1. Deployment 생성

   ```
   kubectl create deployment tcp-echo --image=istio/tcp-echo-server:1.2 --port=9000
   ```
2. Pod 생성 확인

   ```
   kubectl get pod -l app=tcp-echo
   ```
3. AWS Cloud Controller Manager를 통해서 CLB 및 NLB를 생성 및 구성하는 방법 리뷰\
   <https://github.com/kubernetes/cloud-provider-aws/blob/master/docs/service_controller.md>\
   <https://kubernetes.io/docs/concepts/services-networking/service/#aws-nlb-support>
4. Service 생성 &#x20;

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: v1
   kind: Service
   metadata:
     name: tcp-echo
     annotations:
       service.beta.kubernetes.io/aws-load-balancer-type: nlb
   spec:
     selector:
       app: tcp-echo
     ports:
       - protocol: TCP
         port: 9000
         targetPort: 9000
     type: LoadBalancer
   EOF
   ```
5. Service 상태 확인

   ```
   kubectl describe svc tcp-echo
   ```
6. 생성된 ELB 상세 내용 확인

   ```
   aws elbv2 describe-load-balancers --names \
   $(kubectl get svc tcp-echo \
   -o jsonpath='{.status.loadBalancer.ingress[0].hostname}' \
   | grep -o -E '^[a-z0-9]+')
   ```
7. Pod 생성

   ```
   kubectl run netcat --image=youngwjung/netcat -- sleep 3600
   ```
8. Pod 생성 확인&#x20;

   ```
   kubectl get pod netcat
   ```
9. 생성한 Pod에서 NLB로 TCP 연결&#x20;

   ```
   kubectl exec -it netcat -- \
   nc -v -q 1 $(kubectl get svc tcp-echo -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') 9000
   ```
10. 연결에 성공했다는 메시지가 나오면 터미널에 아무 글자나 입력해서 응답이 오는지 확인

    ```
    $ kubectl exec -it netcat -- nc -v -q 1 $(kubectl get svc tcp-echo -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') 9000
    Connection to a0db8c37386d148afbd97efc9dc15a8f-744e5fa4f97a926c.elb.ap-northeast-2.amazonaws.com 9000 port [tcp/*] succeeded!
    kubernetes
    hello kubernetes
    aws
    hello aws
    world
    hello world
    ```
11. 생성한 리소스 삭제&#x20;

    ```
    {
        kubectl delete deploy tcp-echo
        kubectl delete svc tcp-echo
        kubectl delete pod netcat
    }
    ```

### Kubectl Proxy & Port-forwarding

1. Deployment 생성&#x20;

   ```
   kubectl create deployment nginx --image=nginx --port=80 --replicas=1
   ```
2. 생성된 Pod 확인&#x20;

   ```
   kubectl get po -l app=nginx
   ```
3. Service 생성 &#x20;

   ```
   kubectl expose deployment nginx
   ```
4. 생성된 Service 확인&#x20;

   ```
   kubectl get svc nginx
   ```
5. Kubectl proxy 구동&#x20;

   ```
   kubectl proxy --port=8080 --accept-hosts=.* --address=0.0.0.0 
   ```
6. 새로운 터미널을 열고 아래의 주소로 접근 시도

   ```
   curl -L localhost:8080/api/v1/namespaces/default/services/nginx:80/proxy
   ```
7. 생성된 Pod 이름을 환경변수로 저장

   ```
   {
       export POD_NAME=$(kubectl get pod -l app=nginx -o=jsonpath='{.items[0].metadata.name}')
       echo $POD_NAME
   }
   ```
8. 아래의 주소로 접근 시도

   ```
   curl -L localhost:8080/api/v1/namespaces/default/pods/$POD_NAME:80/proxy
   ```
9. 첫번째 터미널로 이동해서 실행중인 kubectl proxy 프로세스 종료&#x20;
10. 생성된 Pod 이름을 환경변수로 저장

    ```
    {
        export POD_NAME=$(kubectl get pod -l app=nginx -o=jsonpath='{.items[0].metadata.name}')
        echo $POD_NAME
    }
    ```
11. 로컬포트를 Pod의 포트로 포워딩

    ```
    kubectl port-forward $POD_NAME 8080:80 --address=0.0.0.0
    ```
12. 다른 터미널로 이동해서 Pod에 배포된 NGINX 서버로 접근 시도&#x20;

    ```
    curl localhost:8080
    ```
13. 첫번째 터미널로 이동해서 실행중인 kubectl port-forward 프로세스 종료&#x20;
14. 로컬포트를 Service의 포트로 포워딩

    ```
    kubectl port-forward svc/nginx 8080:80 --address=0.0.0.0
    ```
15. 다른 터미널로 이동해서 Service로 접근 시도&#x20;

    ```
    curl localhost:8080
    ```
16. 첫번째 터미널로 이동해서 실행중인 kubectl port-forward 프로세스 종료&#x20;
17. 생성한 리소스 삭제&#x20;

    ```
    {
        kubectl delete deploy nginx
        kubectl delete svc nginx
    }
    ```

### ExternalName

1. Service 생성 &#x20;

   ```
   cat <<EOF | kubectl apply -f -
   apiVersion: v1
   kind: Service
   metadata:
     name: k8s
   spec:
     type: ExternalName
     externalName: kubernetes.io
   EOF
   ```
2. Service 상태 확인

   ```
   kubectl describe svc k8s
   ```
3. Pod 생성

   ```
   kubectl run curl --image=curlimages/curl --command -- sleep 3600
   ```
4. 위에서 생성한 Service 호출&#x20;

   ```
   kubectl exec curl -- curl -sL k8s
   ```
5. 위에서 생성한 Service 호출 - *호스트 명시*

   ```
   kubectl exec curl -- curl -sL -H "Host: kubernetes.io" k8s
   ```
6. 위에서 생성한 Service 호출 - *호스트 명시하고 새로운 경로 호출*&#x20;

   ```
   kubectl exec curl -- curl -sL -H "Host: kubernetes.io" k8s/docs
   ```
7. 리소스 삭제

   ```
   {
       kubectl delete svc k8s
       kubectl delete pod curl
   }
   ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://kubernetes.youngwjung.com/core-concepts/service/lab.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
