github.com/openshift/installer@v1.4.17/docs/user/aws/install_upi.md (about)

     1  # Install: User Provided Infrastructure (UPI)
     2  
     3  The steps for performing a UPI-based install are outlined here. Several [CloudFormation][cloudformation] templates are
     4  provided to assist in completing these steps or to help model your own.  You are also free to create the required
     5  resources through other methods; the CloudFormation templates are just an example.
     6  
     7  ## Create Configuration
     8  
     9  Create an install configuration as for [the usual approach](install.md#create-configuration):
    10  
    11  ```console
    12  $ openshift-install create install-config
    13  ? SSH Public Key /home/user_id/.ssh/id_rsa.pub
    14  ? Platform aws
    15  ? Region us-east-2
    16  ? Base Domain example.com
    17  ? Cluster Name openshift
    18  ? Pull Secret [? for help]
    19  ```
    20  
    21  ### Optional: Create Encrypted AMIs
    22  
    23  The IPI-based installer creates an encrypted AMI by default. If you wish to have an encrypted AMI for UPI-based
    24  installs, you will need to create it directly.  See [CoreOS bootimages](../overview.md#coreos-bootimages) for more information
    25  about bootimages, including how to find the AMI identifiers.
    26  
    27  You will make an encrypted copy of the AMI according to the [AWS documentation][encrypted-copy].
    28  
    29  With the new AMI, you can [customize](customization.md) the install-config created on the previous step to override
    30  the default. Additionally, you would pass it to the templates or EC2 launch instance commands according to how
    31  you intend to launch your hosts.
    32  
    33  ### Empty Compute Pools
    34  
    35  We'll be providing the control-plane and compute machines ourselves, so edit the resulting `install-config.yaml` to set `replicas` to 0 for the `compute` pool:
    36  
    37  ```sh
    38  python -c '
    39  import yaml;
    40  path = "install-config.yaml";
    41  data = yaml.load(open(path));
    42  data["compute"][0]["replicas"] = 0;
    43  open(path, "w").write(yaml.dump(data, default_flow_style=False))'
    44  ```
    45  
    46  ## Edit Manifests
    47  
    48  Use [a staged install](../overview.md#multiple-invocations) to make some adjustments which are not exposed via the install configuration.
    49  
    50  ```console
    51  $ openshift-install create manifests
    52  INFO Consuming "Install Config" from target directory
    53  ```
    54  
    55  ### Remove Machines and MachineSets
    56  
    57  Remove the control-plane Machines and compute MachineSets, because we'll be providing those ourselves and don't want to involve [the machine-API operator][machine-api-operator]:
    58  
    59  ```console
    60  $ rm -f openshift/99_openshift-cluster-api_master-machines-*.yaml openshift/99_openshift-cluster-api_worker-machineset-*.yaml 99_openshift-machine-api_master-control-plane-machine-set.yaml
    61  ```
    62  
    63  You are free to leave the compute MachineSets in if you want to create compute machines via the machine API, but if you do you may need to update the various references (`subnet`, etc.) to match your environment.
    64  
    65  ### Make control-plane nodes unschedulable
    66  
    67  Currently [emptying the compute pools](#empty-compute-pools) makes control-plane nodes schedulable.
    68  But due to a [Kubernetes limitation][kubernetes-service-load-balancers-exclude-masters], router pods running on control-plane nodes will not be reachable by the ingress load balancer.
    69  Update the scheduler configuration to keep router pods and other workloads off the control-plane nodes:
    70  
    71  ```sh
    72  python -c '
    73  import yaml;
    74  path = "manifests/cluster-scheduler-02-config.yml"
    75  data = yaml.load(open(path));
    76  data["spec"]["mastersSchedulable"] = False;
    77  open(path, "w").write(yaml.dump(data, default_flow_style=False))'
    78  ```
    79  
    80  ### Adjust DNS Zones
    81  
    82  [The ingress operator][ingress-operator] is able to manage DNS records on your behalf.
    83  Depending on whether you want operator-managed DNS or user-managed DNS, you can choose to [identify the internal DNS zone](#identify-the-internal-dns-zone) or [remove DNS zones](#remove-dns-zones) from the DNS configuration.
    84  
    85  #### Identify the internal DNS zone
    86  
    87  If you want [the ingress operator][ingress-operator] to manage DNS records on your behalf, adjust the `privateZone` section in the DNS configuration to identify the zone it should use.
    88  By default it will use a `kubernetes.io/cluster/{infrastructureName}: owned` tag, but that tag is only appropriate if `openshift-install destroy cluster` should remove the zone.
    89  For user-provided zones, you can remove `tags` completely and use the zone ID instead:
    90  
    91  ```sh
    92  python -c '
    93  import yaml;
    94  path = "manifests/cluster-dns-02-config.yml";
    95  data = yaml.load(open(path));
    96  del data["spec"]["privateZone"]["tags"];
    97  data["spec"]["privateZone"]["id"] = "Z21IZ5YJJMZ2A4";
    98  open(path, "w").write(yaml.dump(data, default_flow_style=False))'
    99  ```
   100  
   101  #### Remove DNS zones
   102  
   103  If you don't want [the ingress operator][ingress-operator] to manage DNS records on your behalf, remove the `privateZone` and `publicZone` sections from the DNS configuration:
   104  
   105  ```sh
   106  python -c '
   107  import yaml;
   108  path = "manifests/cluster-dns-02-config.yml";
   109  data = yaml.load(open(path));
   110  del data["spec"]["publicZone"];
   111  del data["spec"]["privateZone"];
   112  open(path, "w").write(yaml.dump(data, default_flow_style=False))'
   113  ```
   114  
   115  If you do so, you'll need to [add ingress DNS records manually](#add-the-ingress-dns-records) later on.
   116  
   117  #### Disconnected clusters
   118  
   119  For disconnected clusters, Openshift has to be configured [not to manage DNS](#remove-dns-zones), otherwise [the ingress operator][ingress-operator] will try to contact the STS endpoint "sts.amazon.com" directly as opposed to the configured VPC endpoint for the cluster.
   120  
   121  ## Create Ignition Configs
   122  
   123  Now we can create the bootstrap Ignition configs:
   124  
   125  ```console
   126  $ openshift-install create ignition-configs
   127  ```
   128  
   129  After running the command, several files will be available in the directory.
   130  
   131  ```console
   132  $ tree
   133  .
   134  ├── auth
   135  │   └── kubeconfig
   136  ├── bootstrap.ign
   137  ├── master.ign
   138  ├── metadata.json
   139  └── worker.ign
   140  ```
   141  
   142  ### Extract Infrastructure Name from Ignition Metadata
   143  
   144  Many of the operators and functions within OpenShift rely on tagging AWS resources. By default, Ignition
   145  generates a unique cluster identifier comprised of the cluster name specified during the invocation of the installer
   146  and a short string known internally as the infrastructure name. These values are seeded in the initial manifests within
   147  the Ignition configuration. To use the output of the default, generated
   148  `ignition-configs` extracting the internal infrastructure name is necessary.
   149  
   150  An example of a way to get this is below:
   151  
   152  ```
   153  $ jq -r .infraID metadata.json
   154  openshift-vw9j6
   155  ```
   156  
   157  ## Create/Identify the VPC to be Used
   158  
   159  You may create a VPC with various desirable characteristics for your situation (VPN, route tables, etc.). The
   160  VPC configuration and a CloudFormation template is provided [here](../../../upi/aws/cloudformation/01_vpc.yaml).
   161  
   162  A created VPC via the template or manually should approximate a setup similar to this:
   163  
   164  <div style="text-align:center">
   165    <img src="images/install_upi_vpc.svg" width="100%" />
   166  </div>
   167  
   168  ## Create DNS entries and Load Balancers for Control Plane Components
   169  
   170  The DNS and load balancer configuration within a CloudFormation template is provided
   171  [here](../../../upi/aws/cloudformation/02_cluster_infra.yaml). It uses a public hosted zone and creates a private hosted
   172  zone similar to the IPI installation method.
   173  It also creates load balancers, listeners, as well as hosted zone and subnet tags the same way as the IPI
   174  installation method.
   175  This template can be run multiple times within a single VPC and in combination with the VPC
   176  template provided above.
   177  
   178  ### Optional: Manually Create Load Balancer Configuration
   179  
   180  It is needed to create a TCP load balancer for ports 6443 (the Kubernetes API and its extensions) and 22623 (Ignition
   181  configurations for new machines).  The targets will be the master nodes.  Port 6443 must be accessible to both clients
   182  external to the cluster and nodes within the cluster. Port 22623 must be accessible to nodes within the cluster.
   183  
   184  ### Optional: Manually Create Route53 Hosted Zones & Records
   185  
   186  For the cluster name identified earlier in [Create Ignition Configs](#create-ignition-configs), you must create a DNS entry which resolves to your created load balancer.
   187  The entry `api.$clustername.$domain` should point to the external load balancer and `api-int.$clustername.$domain` should point to the internal load balancer.
   188  
   189  ## Create Security Groups and IAM Roles
   190  
   191  The security group and IAM configuration within a CloudFormation template is provided
   192  [here](../../../upi/aws/cloudformation/03_cluster_security.yaml). Run this template to get the minimal and permanent
   193  set of security groups and IAM roles needed for an operational cluster. It can also be inspected for the current
   194  set of required rules to facilitate manual creation.
   195  
   196  ## Launch Temporary Bootstrap Resource
   197  
   198  The bootstrap launch and other necessary, temporary security group plus IAM configuration and a CloudFormation
   199  template is provided [here](../../../upi/aws/cloudformation/04_cluster_bootstrap.yaml). Upload your generated `bootstrap.ign`
   200  file to an S3 bucket in your account and run this template to get a bootstrap node along with a predictable clean up of
   201  the resources when complete. It can also be inspected for the set of required attributes via manual creation.
   202  
   203  ## Launch Permanent Master Nodes
   204  
   205  The master launch and other necessary DNS entries for etcd are provided within a CloudFormation
   206  template [here](../../../upi/aws/cloudformation/05_cluster_master_nodes.yaml). Run this template to get three master
   207  nodes. It can also be inspected for the set of required attributes needed for manual creation of the nodes, DNS entries
   208  and load balancer configuration.
   209  
   210  ## Monitor for `bootstrap-complete` and Initialization
   211  
   212  ```console
   213  $ bin/openshift-install wait-for bootstrap-complete
   214  INFO Waiting up to 30m0s for the Kubernetes API at https://api.test.example.com:6443...
   215  INFO API v1.12.4+c53f462 up
   216  INFO Waiting up to 30m0s for the bootstrap-complete event...
   217  ```
   218  
   219  ## Destroy Bootstrap Resources
   220  
   221  At this point, you should delete the bootstrap resources. If using the CloudFormation template, you would [delete the
   222  stack][delete-stack] created for the bootstrap to clean up all the temporary resources.
   223  
   224  ## Launch Additional Compute Nodes
   225  
   226  You may create compute nodes by launching individual EC2 instances discretely or by automated processes outside the cluster (e.g. Auto Scaling Groups).
   227  You can also take advantage of the built in cluster scaling mechanisms and the machine API in OpenShift, as mentioned [above](#create-ignition-configs).
   228  In this example, we'll manually launch instances via the CloudFormatio template [here](../../../upi/aws/cloudformation/06_cluster_worker_node.yaml).
   229  You can launch a CloudFormation stack to manage each individual compute node (you should launch at least two for a high-availability ingress router).
   230  A similar launch configuration could be used by outside automation or AWS auto scaling groups.
   231  
   232  #### Approving the CSR requests for nodes
   233  
   234  The CSR requests for client and server certificates for nodes joining the cluster will need to be approved by the administrator.
   235  You can view them with:
   236  
   237  ```console
   238  $ oc get csr
   239  NAME        AGE     REQUESTOR                                                                   CONDITION
   240  csr-8b2br   15m     system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
   241  csr-8vnps   15m     system:serviceaccount:openshift-machine-config-operator:node-bootstrapper   Approved,Issued
   242  csr-b96j4   25s     system:node:ip-10-0-52-215.us-east-2.compute.internal                       Approved,Issued
   243  csr-bfd72   5m26s   system:node:ip-10-0-50-126.us-east-2.compute.internal                       Pending
   244  csr-c57lv   5m26s   system:node:ip-10-0-95-157.us-east-2.compute.internal                       Pending
   245  ...
   246  ```
   247  
   248  Administrators should carefully examine each CSR request and approve only the ones that belong to the nodes created by them.
   249  CSRs can be approved by name, for example:
   250  
   251  ```sh
   252  oc adm certificate approve csr-bfd72
   253  ```
   254  
   255  ## Add the Ingress DNS Records
   256  
   257  If you removed the DNS Zone configuration [earlier](#remove-dns-zones), you'll need to manually create some DNS records pointing at the ingress load balancer.
   258  You can create either a wildcard `*.apps.{baseDomain}.` or specific records (more on the specific records below).
   259  You can use A, CNAME, [alias][route53-alias], etc. records, as you see fit.
   260  For example, you can create wildcard alias records by retrieving the ingress load balancer status:
   261  
   262  ```console
   263  $ oc -n openshift-ingress get service router-default
   264  NAME             TYPE           CLUSTER-IP      EXTERNAL-IP                                                              PORT(S)                      AGE
   265  router-default   LoadBalancer   172.30.62.215   ab37f072ec51d11e98a7a02ae97362dd-240922428.us-east-2.elb.amazonaws.com   80:31499/TCP,443:30693/TCP   5m
   266  ```
   267  
   268  Then find the hosted zone ID for the load balancer (or use [this table][route53-zones-for-load-balancers]):
   269  
   270  ```console
   271  $ aws elb describe-load-balancers | jq -r '.LoadBalancerDescriptions[] | select(.DNSName == "ab37f072ec51d11e98a7a02ae97362dd-240922428.us-east-2.elb.amazonaws.com").CanonicalHostedZoneNameID'
   272  Z3AADJGX6KTTL2
   273  ```
   274  
   275  And finally, add the alias records to your private and public zones:
   276  
   277  ```console
   278  $ aws route53 change-resource-record-sets --hosted-zone-id "${YOUR_PRIVATE_ZONE}" --change-batch '{
   279  >   "Changes": [
   280  >     {
   281  >       "Action": "CREATE",
   282  >       "ResourceRecordSet": {
   283  >         "Name": "\\052.apps.your.cluster.domain.example.com",
   284  >         "Type": "A",
   285  >         "AliasTarget":{
   286  >           "HostedZoneId": "Z3AADJGX6KTTL2",
   287  >           "DNSName": "ab37f072ec51d11e98a7a02ae97362dd-240922428.us-east-2.elb.amazonaws.com.",
   288  >           "EvaluateTargetHealth": false
   289  >         }
   290  >       }
   291  >     }
   292  >   ]
   293  > }'
   294  $ aws route53 change-resource-record-sets --hosted-zone-id "${YOUR_PUBLIC_ZONE}" --change-batch '{
   295  >   "Changes": [
   296  >     {
   297  >       "Action": "CREATE",
   298  >       "ResourceRecordSet": {
   299  >         "Name": "\\052.apps.your.cluster.domain.example.com",
   300  >         "Type": "A",
   301  >         "AliasTarget":{
   302  >           "HostedZoneId": "Z3AADJGX6KTTL2",
   303  >           "DNSName": "ab37f072ec51d11e98a7a02ae97362dd-240922428.us-east-2.elb.amazonaws.com.",
   304  >           "EvaluateTargetHealth": false
   305  >         }
   306  >       }
   307  >     }
   308  >   ]
   309  > }'
   310  ```
   311  
   312  If you prefer to add explicit domains instead of using a wildcard, you can create entries for each of the cluster's current routes:
   313  
   314  ```console
   315  $ oc get --all-namespaces -o jsonpath='{range .items[*]}{range .status.ingress[*]}{.host}{"\n"}{end}{end}' routes
   316  oauth-openshift.apps.your.cluster.domain.example.com
   317  console-openshift-console.apps.your.cluster.domain.example.com
   318  downloads-openshift-console.apps.your.cluster.domain.example.com
   319  alertmanager-main-openshift-monitoring.apps.your.cluster.domain.example.com
   320  grafana-openshift-monitoring.apps.your.cluster.domain.example.com
   321  prometheus-k8s-openshift-monitoring.apps.your.cluster.domain.example.com
   322  ```
   323  
   324  ## Monitor for Cluster Completion
   325  
   326  ```console
   327  $ bin/openshift-install wait-for install-complete
   328  INFO Waiting up to 30m0s for the cluster to initialize...
   329  ```
   330  
   331  Also, you can observe the running state of your cluster pods:
   332  
   333  ```console
   334  $ oc get pods --all-namespaces
   335  NAMESPACE                                               NAME                                                                READY     STATUS      RESTARTS   AGE
   336  kube-system                                             etcd-member-ip-10-0-3-111.us-east-2.compute.internal                1/1       Running     0          35m
   337  kube-system                                             etcd-member-ip-10-0-3-239.us-east-2.compute.internal                1/1       Running     0          37m
   338  kube-system                                             etcd-member-ip-10-0-3-24.us-east-2.compute.internal                 1/1       Running     0          35m
   339  openshift-apiserver-operator                            openshift-apiserver-operator-6d6674f4f4-h7t2t                       1/1       Running     1          37m
   340  openshift-apiserver                                     apiserver-fm48r                                                     1/1       Running     0          30m
   341  openshift-apiserver                                     apiserver-fxkvv                                                     1/1       Running     0          29m
   342  openshift-apiserver                                     apiserver-q85nm                                                     1/1       Running     0          29m
   343  ...
   344  openshift-service-ca-operator                           openshift-service-ca-operator-66ff6dc6cd-9r257                      1/1       Running     0          37m
   345  openshift-service-ca                                    apiservice-cabundle-injector-695b6bcbc-cl5hm                        1/1       Running     0          35m
   346  openshift-service-ca                                    configmap-cabundle-injector-8498544d7-25qn6                         1/1       Running     0          35m
   347  openshift-service-ca                                    service-serving-cert-signer-6445fc9c6-wqdqn                         1/1       Running     0          35m
   348  openshift-service-catalog-apiserver-operator            openshift-service-catalog-apiserver-operator-549f44668b-b5q2w       1/1       Running     0          32m
   349  openshift-service-catalog-controller-manager-operator   openshift-service-catalog-controller-manager-operator-b78cr2lnm     1/1       Running     0          31m
   350  ```
   351  
   352  [cloudformation]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/Welcome.html
   353  [delete-stack]: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cfn-console-delete-stack.html
   354  [ingress-operator]: https://github.com/openshift/cluster-ingress-operator
   355  [kubernetes-service-load-balancers-exclude-masters]: https://github.com/kubernetes/kubernetes/issues/65618
   356  [machine-api-operator]: https://github.com/openshift/machine-api-operator
   357  [route53-alias]: https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/resource-record-sets-choosing-alias-non-alias.html
   358  [route53-zones-for-load-balancers]: https://docs.aws.amazon.com/general/latest/gr/rande.html#elb_region
   359  [encrypted-copy]: https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AMIEncryption.html#create-ami-encrypted-root-snapshot