ノート:

Oracle LinuxでKubernetesを実行

イントロダクション

Kubernetesは、パイロットやヘルムスマンのためにギリシャ語です。つまり、コマンドにたどり着いて船を究極の目標(注文船長ではなく)に向けて送る人です。そのため、Kubernetesは、コンテナ化されたアプリケーションをデプロイ、管理およびスケーリングするためのオープンソースの拡張可能なプラットフォームです。これは、いくつかのコマンドライン・ツールを使用して実現します。このラボでは、kubectlと呼ばれる属性の1つをYAMLファイルとともに使用して、アプリケーションをデプロイする組織に必要な属性を定義し、アプリケーションのデプロイ後にアプリケーションを設定および保守する方法を理解します。

Kubernetesクラスタへのすべてのデプロイメントは、オブジェクトとして表されます。これらのデプロイ済オブジェクトは、テキストベースのYAMLファイルを使用して、クラスタにデプロイされたアプリケーションの必要な状態の詳細を提供します。これらのYAMLファイルでは、次のことが説明されます。

この3番目のポイントは、基本を理解せずに複雑です。したがって、このトピックは、今後のチュートリアルで取り扱います。

このチュートリアルは、Oracle LinuxのコンパクトなOracle Cloud Native Environment内で実行されるKubernetesと連携します。目的は、本番デプロイメントの管理に必要なすべてのものにとって「ワン・ストップ・ショップ」ではありません。かわりに、サンプル・アプリケーションをデプロイするために必要なスキルを紹介します。

目的

前提条件

次の構成を持つ Oracle Linux 8以降のシステム:

演習環境の設定

ノート: 無料ラボ環境を使用する場合、接続およびその他の使用手順については、Oracle Linux Labの基本を参照してください。

情報: 無料ラボ環境では、環境を作成する準備ができて、提供されたノードにOracle Cloud Native Environmentをデプロイします。このデプロイメントは、起動後に終了するまでに約8分から10分かかります。したがって、この実行中にステップ・アウトし、演習を完了するために戻ります。

  1. まだ接続されていない場合は、端末を開き、sshを使用して ocne-node01システムに接続します。

    ssh oracle@<ip_address_of_ol_node>
    
  2. 環境の準備ができていることを確認します。

    kubectl get pods -A
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get pods -A
    NAMESPACE                      NAME                                             READY   STATUS    RESTARTS   AGE
    externalip-validation-system   externalip-validation-webhook-7988bff847-8ws2v   1/1     Running   0          3m18s
    kube-system                    coredns-7cbc77dbc7-qxqth                         1/1     Running   0          3m18s
    kube-system                    coredns-7cbc77dbc7-r9bgj                         1/1     Running   0          3m18s
    kube-system                    etcd-ocne-node01                                 1/1     Running   0          3m37s
    kube-system                    kube-apiserver-ocne-node01                       1/1     Running   0          3m37s
    kube-system                    kube-controller-manager-ocne-node01              1/1     Running   0          3m37s
    kube-system                    kube-flannel-ds-vcwzn                            1/1     Running   0          3m18s
    kube-system                    kube-proxy-7lx59                                 1/1     Running   0          3m18s
    kube-system                    kube-scheduler-ocne-node01                       1/1     Running   0          3m37s
    kubernetes-dashboard           kubernetes-dashboard-5d5d4947b5-7pffh            1/1     Running   0          3m18s
    

ポッドおよびリクエストの詳細でのデプロイメントの作成

Kubernetesでは、deploymentは、ポッドの動作と特性を制御するファイルを参照する技術用語です。管理者はデプロイメントを使用してアプリケーションに何をするかを指示し、Kubernetesはその状態に達するためにタスクを実行します。

この例では、HTTPヘッダーを介して受信したリクエストのソースIPをエコー・バックする小さなnginx Webサーバーを含むイメージを使用しています。

  1. echoserverの配備を作成します。

    kubectl create deployment test --image=k8s.gcr.io/echoserver:1.4
    
  2. クラスタ内のすべてのポッドをリストします。

    kubectl get pods
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get pods
    NAME                    READY   STATUS    RESTARTS   AGE
    test-6c486b6d76-467p7   1/1     Running   0          53s
    

    ノート: ポッド名には、ポッドをデプロイするたびに変化する接尾辞値が含まれます。

  3. JSONPathを使用して、ポッド名を変数に割り当てます。

    TESTPOD=$(kubectl get pods -o jsonpath='{ $.items[*].metadata.name }')
    
  4. 変数の割当てをテストします。

    kubectl get podsコマンドでは、ポッド名をパラメータとして渡して、そのポッドの情報のみを表示することもできます。

    kubectl get pods $TESTPOD
    
  5. ポッドに関する選択した情報を要求します。

    kubectl get pod $TESTPOD --output custom-columns=NAME:metadata.name,NODE_IP:status.hostIP,POD_IP:status.podIP
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get pod $TESTPOD --output custom-columns=NAME:metadata.name,NODE_IP:status.hostIP,POD_IP:status.podIP
    NAME                    NODE_IP      POD_IP
    test-6c486b6d76-467p7   10.0.0.140   10.244.0.7
    
  6. ポッドの詳細を取得します。

    kubectl describe pod $TESTPOD
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl describe pod test-6c486b6d76-467p7
    Name:         test-6c486b6d76-467p7
    Namespace:    default
    Priority:     0
    Node:         ocne-node01/10.0.0.140
    Start Time:   Tue, 28 Jun 2022 19:21:27 +0000
    Labels:       app=test
                  pod-template-hash=6c486b6d76
    Annotations:  <none>
    Status:       Running
    IP:           10.244.0.7
    IPs:
      IP:           10.244.0.7
    Controlled By:  ReplicaSet/test-6c486b6d76
    Containers:
      echoserver:
        Container ID:   cri-o://5b7866a27722ec0998cd9fe74945fb82b4dd9ed4c5c80671d9e8aa239c7008a4
        Image:          k8s.gcr.io/echoserver:1.4
        Image ID:       k8s.gcr.io/echoserver@sha256:5d99aa1120524c801bc8c1a7077e8f5ec122ba16b6dda1a5d3826057f67b9bcb
        Port:           <none>
        Host Port:      <none>
        State:          Running
          Started:      Tue, 28 Jun 2022 19:21:30 +0000
        Ready:          True
        Restart Count:  0
        Environment:    <none>
        Mounts:
          /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-d67ph (ro)
    Conditions:
      Type              Status
      Initialized       True 
      Ready             True 
      ContainersReady   True 
      PodScheduled      True 
    Volumes:
      kube-api-access-d67ph:
        Type:                    Projected (a volume that contains injected data from multiple sources)
        TokenExpirationSeconds:  3607
        ConfigMapName:           kube-root-ca.crt
        ConfigMapOptional:       <nil>
        DownwardAPI:             true
    QoS Class:                   BestEffort
    Node-Selectors:              <none>
    Tolerations:                 node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
                                 node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
    Events:
      Type    Reason     Age   From               Message
      ----    ------     ----  ----               -------
      Normal  Scheduled  21m   default-scheduler  Successfully assigned default/test-6c486b6d76-467p7 to ocne-node01
      Normal  Pulling    21m   kubelet            Pulling image "k8s.gcr.io/echoserver:1.4"
      Normal  Pulled     21m   kubelet            Successfully pulled image "k8s.gcr.io/echoserver:1.4" in 3.102843235s
      Normal  Created    21m   kubelet            Created container echoserver
      Normal  Started    21m   kubelet            Started container echoserver
    

YAMLファイルを使用したデプロイメントの作成

Kubernetesのデプロイメント・マニフェストを使用して、アプリケーションをKubernetesクラスタにデプロイする方法を定義し、自己修復、スケーラビリティ、バージョニングおよびローリング更新などの他のKubernetes機能へのアクセスを提供します。このラボでは、Kubernetes内で提供されるこのより複雑な機能に対処しません。かわりに、非常に基本的なマニフェスト・ファイルを使用してアプリケーションをデプロイする方法を説明します。

デプロイメント・マニフェスト・ファイルは、JSONまたはYAMLで書き込まれます。JSONを使用できますが、YAMLは柔軟性、可読性、最終的なデプロイメントの側面を明確にする説明コメントを含める機能により、非常に人気があります。

デプロイメントを実行すると、ポッドは一連の宣言的更新によって更新され、実行中のアプリケーションの目的の状態に到達します。

deployment.yamlのすべての詳細は、Kubernetesがデプロイメント・リクエストを実施できるようにするには不可欠ですが、次の点がより重要な部分を示しています。

これらの他のフィールドの詳細は、上流のデプロイメントのドキュメントを参照してください。

  1. デプロイメント・ファイルを作成します。

    cat << 'EOF' | tee mydeployment.yaml > /dev/null
    apiVersion: apps/v1
    kind: Deployment
    metadata:
     name: echo1
    spec:
     selector:
       matchLabels: 
         app: echo1
     template:
       metadata:
         labels:
           app: echo1
       spec:
         containers:
         - name: echoserver
           image: k8s.gcr.io/echoserver:1.4
    EOF
    
  2. デプロイメント・マニフェスト・ファイルを使用して、アプリケーションをポッドにデプロイします。

    kubectl apply -f mydeployment.yaml
    

    出力例:

    [[oracle@ocne-node01 ~]$ kubectl apply -f mydeployment.yaml
    deployment.apps/echo1 created
    
  3. デプロイメントによって管理されるポッドをリストします。

    kubectl get pods -l app=echo1
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get pods -l app=echo1
    NAME                     READY   STATUS    RESTARTS   AGE
    echo1-7cbf6dfb96-4cgq7   1/1     Running   0          24s
    
    • -lまたは--selector=オプションは、フィルタ対象のセレクタ(ラベル問合せ)を提供します。このオプションでは、'= '、'= = 'および'!= 'がサポートされます。(例: -l key1=value1,key2=value2)

    ノート: ポッド名には、ポッドをデプロイするたびに変化する接尾辞値が含まれていることに注意してください。

  4. デプロイメントが成功したことを確認します。

    kubectl get deploy echo1
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get deploy echo1
    NAME    READY   UP-TO-DATE   AVAILABLE   AGE
    echo1   1/1     1            1           16m
    
    • deployオプションは、deploymentsでは短くなっています。kubectlコマンドでは、そのオプションの多くに省略された構文を使用できます。詳細は、kubectl --helpを実行して入手できます。
  5. デプロイメントの詳細情報を返します。

    kubectl describe deploy echo1
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl describe deploy echo1
    Name:                   echo1
    Namespace:              default
    CreationTimestamp:      Tue, 28 Jun 2022 20:20:40 +0000
    Labels:                 <none>
    Annotations:            deployment.kubernetes.io/revision: 1
    Selector:               app=echo1
    Replicas:               1 desired | 1 updated | 1 total | 1 available | 0 unavailable
    StrategyType:           RollingUpdate
    MinReadySeconds:        0
    RollingUpdateStrategy:  25% max unavailable, 25% max surge
    Pod Template:
      Labels:  app=echo1
      Containers:
       echoserver:
        Image:        k8s.gcr.io/echoserver:1.4
        Port:         <none>
        Host Port:    <none>
        Environment:  <none>
        Mounts:       <none>
      Volumes:        <none>
    Conditions:
      Type           Status  Reason
      ----           ------  ------
      Available      True    MinimumReplicasAvailable
      Progressing    True    NewReplicaSetAvailable
    OldReplicaSets:  <none>
    NewReplicaSet:   echo1-7cbf6dfb96 (1/1 replicas created)
    Events:
      Type    Reason             Age   From                   Message
      ----    ------             ----  ----                   -------
      Normal  ScalingReplicaSet  23m   deployment-controller  Scaled up replica set echo1-7cbf6dfb96 to 1
    

ClusterIPサービスの使用

echo1 Deploymentをポッドに正常にデプロイしても、エンドユーザーが内部またはネットワーク上でアクセスできない場合、あまり使用されません。そのアクセスでは、サービスがネットワークにデプロイメントを公開する際に便利です。

デフォルトのKubernetesサービス・タイプはClusterIPです。ただし、インターネットからClusterIPサービスにアクセスすることはできませんが、Kubernetesプロキシを使用できます。プロキシの詳細は、アップストリームのドキュメントを参照してください。

この項では、echo1を公開し、Oracle Linuxポッドを使用してクラスタ内でサービス間通信を作成し、アプリケーションのフロントエンド・コンポーネントとバックエンド・コンポーネント間の通信を示します。

  1. ノードのリストを取得します。

    kubectl get nodes
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get nodes
    NAME          STATUS   ROLES    AGE     VERSION
    ocne-node01   Ready    <none>   4h27m   v1.22.8+1.el8
    

    ノードは、ポッドをデプロイするための物理システムまたは仮想マシンです。

  2. kube- proxyモードをクエリーします。

    kube- proxyiptablesモードで実行すると、ClusterIPサービスに送信されるパケットはソースNAT'dになりません。

    curl -w "\n" http://localhost:10249/proxyMode
    
    • kube- proxyは、ポート10249が動作しているノードで待機します。
  3. ClusterIPサービスを作成します。

    kubectl expose deployment echo1 --name=clusterip-service --port=80 --target-port=8080
    
  4. クラスタに割り当てられたIPアドレスを取得します。

    kubectl get svc clusterip-service
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get svc clusterip-service
    NAME                TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    clusterip-service   ClusterIP   10.108.107.54   <none>        80/TCP    13s
    

    出力のCLUSTER-IPアドレスをノートにとります。

  5. ClusterIPサービスにアクセスするためのポッドを同じクラスタに作成します。

    kubectl run ol -it --image=oraclelinux:8 --restart=Never --rm
    

    このコマンドは、対話型モードでOracle Linux 8コンテナを実行しているポッドを作成し、コマンド・プロンプトを表示します。

    出力例:

    [oracle@ocne-node01 ~]$ kubectl run ol -it --image=oraclelinux:8 --restart=Never --rm
    If you don't see a command prompt, try pressing enter.
    [root@ol /]#
    
  6. Oracle LinuxコンテナのIPアドレスを取得します。

    ip -br a
    

    出力例:

    [root@ol /]# ip -br a
    lo               UNKNOWN        127.0.0.1/8 ::1/128 
    eth0@if12        UP             10.244.0.9/24 fe80::146f:2cff:fe73:b528/64
    
  7. echo1内でnginx Webサーバーをテストします。

    curl -w "\n" <CLUSTER-IP_ADDRESS>
    

    前の出力のCLUSTER-IPアドレスを使用します。

    出力例:

    [root@ol /]# curl -w "\n" 10.108.107.54
    CLIENT VALUES:
    client_address=10.244.0.9
    command=GET
    real path=/
    query=nil
    request_version=1.1
    request_uri=http://10.108.107.54:8080/
    
    SERVER VALUES:
    server_version=nginx: 1.10.0 - lua: 10001
    
    HEADERS RECEIVED:
    accept=*/*
    host=10.108.107.54
    user-agent=curl/7.61.1
    BODY:
    -no body in request-
    

    出力には、Oracle Linuxからのリクエストが表示され、echo1デプロイメントを使用したClusterIPサービスによって処理されます。

  8. コンテナを終了します。

    exit
    

    出力例:

    [root@ol /]# exit
    exit
    pod "ol" deleted
    

YAMLファイルでのNodePortサービスの使用

以前は、echo1デプロイメントはkubectl exposeコマンドを使用して公開され、ClusterIPを使用して内部的にアクセスされました。ここで、NodePortサービスを使用します。これは、echo1にネットワーク経由で外部からアクセスできるようにするための開発者のアプローチです。

NodePortサービスは、すべてのノードで特定のポートを開き、トラフィックをそのポートにサービスに転送します。

ノート Standardの演習では、主に次の理由から、本番システムにNodePortを使用することはお薦めしません。

  1. サービス・ファイルを定義します。

    cat << 'EOF' | tee myservice.yaml > /dev/null
    apiVersion: v1
    kind: Service
    metadata:
      name: echo1-nodeport
      namespace: default
    spec:
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - nodePort: 32387
        port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: echo1
      sessionAffinity: None
      type: NodePort
    status:
      loadBalancer: {}
    EOF
    
    • type: サービスを外部クライアントからのネットワーク要求で使用できるようにします。有効な値は、nodePort、LooadBalancerです。
    • nodePort: サービスへのアクセスに使用される外部ポート。
    • port: - クラスタ内で公開されているポート番号。
    • targetPort: コンテナがリスニングしているポート。
  2. サービスを作成します。

    kubectl apply -f myservice.yaml
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl apply -f myservice.yaml 
    service/echo1 created
    

    ノート: アプリケーションの管理を簡素化するために、デプロイメントおよびサービス定義を同じYAMLファイルに含めることが一般的です。これらのステップで個別のファイルを使用することは、トレーニングのみを目的としています。1つのファイルに結合する場合は、--- YAML構文を使用してそれらを区切ります。

  3. 新しく作成されたサービスをKubernetesがどのように保存するかを表示します。

    kubectl get service echo1-nodeport -o yaml
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get service echo1-nodeport -o yaml
    apiVersion: v1
    kind: Service
    metadata:
      annotations:
        kubectl.kubernetes.io/last-applied-configuration: |
          {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"name":"echo1-nodeport","namespace":"default"},"spec":{"ipFamilies":["IPv4"],"ipFamilyPolicy":"SingleStack","ports":[{"nodePort":32387,"port":80,"protocol":"TCP","targetPort":8080}],"selector":{"app":"echo1"},"sessionAffinity":"None","type":"NodePort"},"status":{"loadBalancer":{}}}
      creationTimestamp: "2022-06-29T00:14:30Z"
      name: echo1-nodeport
      namespace: default
      resourceVersion: "6242"
      uid: 3171dda6-05b8-45b8-a0ba-457eab6e4f71
    spec:
      clusterIP: 10.100.17.53
      clusterIPs:
      - 10.100.17.53
      externalTrafficPolicy: Cluster
      internalTrafficPolicy: Cluster
      ipFamilies:
      - IPv4
      ipFamilyPolicy: SingleStack
      ports:
      - nodePort: 32387
        port: 80
        protocol: TCP
        targetPort: 8080
      selector:
        app: echo1
      sessionAffinity: None
      type: NodePort
    status:
      loadBalancer: {}
    
  4. Podsサービスの説明

    kubectl describe svc echo1-nodeport
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl describe svc echo1-nodeport
    Name:                     echo1-nodeport
    Namespace:                default
    Labels:                   <none>
    Annotations:              <none>
    Selector:                 app=echo1
    Type:                     NodePort
    IP Family Policy:         SingleStack
    IP Families:              IPv4
    IP:                       10.100.17.53
    IPs:                      10.100.17.53
    Port:                     <unset>  80/TCP
    TargetPort:               8080/TCP
    NodePort:                 <unset>  32387/TCP
    Endpoints:                10.244.0.7:8080
    Session Affinity:         None
    External Traffic Policy:  Cluster
    Events:                   <none>
    
  5. オブジェクト・エンドポイントを取得します。

    エンドポイントは、サービスがトラフィックを送信するポッドのIPアドレスを追跡します。

    kubectl get endpoints echo1-nodeport
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get endpoints echo1-nodeport
    NAME             ENDPOINTS         AGE
    echo1-nodeport   10.244.0.7:8080   8m39s
    
  6. アプリケーションを実行しているポッドをリストします。

    kubectl get pods --output=wide
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get pods -o wide
    NAME                     READY   STATUS    RESTARTS   AGE   IP           NODE          NOMINATED NODE   READINESS GATES
    echo1-7cbf6dfb96-mlds4   1/1     Running   0          80m   10.244.0.7   ocne-node01   <none>           <none>
    test-6c486b6d76-v4htj    1/1     Running   0          83m   10.244.0.6   ocne-node01   <none>           <none>
    

    echo1のこのリストの IPアドレスは、指定したノードで実行されているポッドのIPアドレスであるエンドポイントの前の手順に示されている値と一致する必要があります。

  7. サービスをリストします。

    kubectl get svc -o wide
    

    出力例:

    [oracle@ocne-node01 ~]$ kubectl get svc -o wide
    NAME                TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE   SELECTOR
    clusterip-service   ClusterIP   10.107.31.75   <none>        80/TCP         78m   app=echo1
    echo1-nodeport      NodePort    10.100.17.53   <none>        80:32387/TCP   10m   app=echo1
    kubernetes          ClusterIP   10.96.0.1      <none>        443/TCP        88m   <none>
    

    このコマンドは、--output=wideではなく -o wideの代替オプションを使用しました。

    echo1-nodeportサービスの 32387に設定されている NodePortをノートにとります。

  8. ノードのIPアドレスを取得します。

    フリー・ラボ環境は、単一のノードocne-node01で実行されます。

    ip -br a
    

    無料ラボ環境では、IPアドレスは、インタフェースens3に割り当てられたインスタンスのプライベートIPアドレス10.0.0.140を返す必要があります。

  9. JSONPathを使用して、NodePortに変数を割り当てます。

    NODEPORT=$(kubectl get -o jsonpath="{.spec.ports[0].nodePort}" services echo1-nodeport)
    
  10. JSONPathを使用して、ノードIPを変数に割り当てます。

    NODES=$(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }')
    
  11. ファイアウォール・ルールを作成します。

    このルールにより、node:nodeportのトラフィックが許可されます。nodeは、Podが実行されているシステムまたは仮想マシンのホストIPアドレスです。

    sudo firewall-cmd --permanent --add-port=$NODEPORT/tcp
    sudo firewall-cmd --reload
    

    --reloadの後、firewalldデーモンは、iptablesを含む構成を再ロードします。kube- proxyはiptablesに依存するため、サービスからのレスポンスに遅延が発生します。

  12. ノード・アドレスとノード・ポートを使用して、アプリケーションを確認します。

    curl -s $NODES:$NODEPORT
    

    出力例:

    [oracle@ocne-node01 ~]$ curl -s $NODES:NODEPORT
    CLIENT VALUES:
    client_address=10.244.0.1
    command=GET
    real path=/
    query=nil
    request_version=1.1
    request_uri=http://10.0.0.140:8080/
    
    SERVER VALUES:
    server_version=nginx: 1.10.0 - lua: 10001
    
    HEADERS RECEIVED:
    accept=*/*
    host=10.0.0.140:32387
    user-agent=curl/7.61.1
    BODY:
    

    この出力は、NodePortサービス、kube- proxy、および echo1デプロイメントを実行しているポッドを介したローカルノードルーティングからのリクエストを示しています。

    ノート: 出力がハングアップしたように見える場合、これはファイアウォールの以前のリロードによるものです。Ctrl-Cと入力して再試行してください。

デプロイメントとサービスの削除

サービスまたはデプロイメントが完了したら、それらをKubernetesから削除します。

  1. サービスを削除します。

    kubectl delete svc clusterip-service echo1-nodeport
    
  2. デプロイメントを削除します。

    kubectl delete deployments echo1
    kubectl delete deploy test
    

オブジェクトの削除は、個別にまたはグループで実行できます。詳細は、Kubernetesリファレンス・マニュアルを参照してください。

概要

このラボでは、Kubernetesのようなクラウドネイティブ・オーケストレータを使用する機能が、Kubernetesを使用してコンテナ・デプロイメントを管理するすべての組織に提供する最も簡単な概要を示します。これらの演習は、Kubernetesを使用して提供できる柔軟性を実現する長い旅になる可能性が最も高いものの最初のステップを提供します。

詳細情報

その他の学習リソース

他のラボをdocs.oracle.com/learnで探すか、Oracle Learning YouTubeチャネルでより無料の学習コンテンツにアクセスします。また、education.oracle.com/learning-explorerにアクセスしてOracle Learning Explorerになります。

製品のドキュメントは、Oracle Help Centerを参照してください。