feat: add oraclecloud.com platform support
* cloud-init for oraclecloud (IMDSv2) * amd64/arm64 arch * set DHCPv6 on if IPv6 subnet allocated Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev> Signed-off-by: Andrey Smirnov <andrey.smirnov@talos-systems.com>
This commit is contained in:
parent
f3ec24bebf
commit
2869b5eeac
@ -556,6 +556,8 @@ local release = {
|
||||
'_out/nocloud-arm64.raw.xz',
|
||||
'_out/openstack-amd64.tar.gz',
|
||||
'_out/openstack-arm64.tar.gz',
|
||||
'_out/oracle-amd64.qcow2.xz',
|
||||
'_out/oracle-arm64.qcow2.xz',
|
||||
'_out/scaleway-amd64.raw.xz',
|
||||
'_out/scaleway-arm64.raw.xz',
|
||||
'_out/talos-amd64.iso',
|
||||
|
2
Makefile
2
Makefile
@ -228,7 +228,7 @@ image-%: ## Builds the specified image. Valid options are aws, azure, digital-oc
|
||||
|
||||
images-essential: image-aws image-gcp image-metal ## Builds only essential images used in the CI (AWS, GCP, and Metal).
|
||||
|
||||
images: image-aws image-azure image-digital-ocean image-gcp image-hcloud image-metal image-nocloud image-openstack image-scaleway image-upcloud image-vmware image-vultr ## Builds all known images (AWS, Azure, DigitalOcean, GCP, HCloud, Metal, NoCloud, Openstack, Scaleway, UpCloud, Vultr and VMware).
|
||||
images: image-aws image-azure image-digital-ocean image-gcp image-hcloud image-metal image-nocloud image-openstack image-oracle image-scaleway image-upcloud image-vmware image-vultr ## Builds all known images (AWS, Azure, DigitalOcean, GCP, HCloud, Metal, NoCloud, Openstack, Oracle, Scaleway, UpCloud, Vultr and VMware).
|
||||
|
||||
sbc-%: ## Builds the specified SBC image. Valid options are rpi_4, rock64, bananapi_m64, libretech_all_h3_cc_h5, rockpi_4 and pine64 (e.g. sbc-rpi_4)
|
||||
@docker pull $(REGISTRY_AND_USERNAME)/imager:$(IMAGE_TAG)
|
||||
|
@ -84,7 +84,7 @@ func runImageCmd() (err error) {
|
||||
|
||||
if options.ConfigSource == "" {
|
||||
switch p.Name() {
|
||||
case "aws", "azure", "digital-ocean", "gcp", "hcloud", "nocloud", "scaleway", "upcloud", "vultr":
|
||||
case "aws", "azure", "digital-ocean", "gcp", "hcloud", "nocloud", "oracle", "scaleway", "upcloud", "vultr":
|
||||
options.ConfigSource = constants.ConfigNone
|
||||
case "vmware":
|
||||
options.ConfigSource = constants.ConfigGuestInfo
|
||||
@ -169,6 +169,19 @@ func finalize(platform runtime.Platform, img, arch string) (err error) {
|
||||
if err = tar(fmt.Sprintf("openstack-%s.tar.gz", arch), file, dir); err != nil {
|
||||
return err
|
||||
}
|
||||
case "oracle":
|
||||
name = fmt.Sprintf("oracle-%s.qcow2", arch)
|
||||
file = filepath.Join(outputArg, name)
|
||||
|
||||
if err = qemuimg.Convert("raw", "qcow2", "cluster_size=8k", img, file); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Println("compressing image")
|
||||
|
||||
if err = xz(file); err != nil {
|
||||
return err
|
||||
}
|
||||
case "scaleway":
|
||||
file = filepath.Join(outputArg, fmt.Sprintf("scaleway-%s.raw", arch))
|
||||
|
||||
|
@ -52,6 +52,13 @@ Talos now preserves machine configuration as it was submitted to the node.
|
||||
There is some work still going on various cloud platforms to stop modifying machine configuration on the fly.
|
||||
"""
|
||||
|
||||
[notes.platforms]
|
||||
title = "Platform Support"
|
||||
description="""\
|
||||
Talos now supports Oracle Cloud.
|
||||
"""
|
||||
|
||||
|
||||
[make_deps]
|
||||
|
||||
[make_deps.tools]
|
||||
|
@ -0,0 +1,164 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package oracle
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
|
||||
"github.com/AlekSi/pointer"
|
||||
"github.com/talos-systems/go-procfs/procfs"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/errors"
|
||||
"github.com/talos-systems/talos/pkg/download"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config/configloader"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
// Ref: https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/gettingmetadata.htm
|
||||
const (
|
||||
// OracleHostnameEndpoint is the local metadata endpoint for the hostname.
|
||||
OracleHostnameEndpoint = "http://169.254.169.254/opc/v2/instance/hostname"
|
||||
// OracleUserDataEndpoint is the local metadata endpoint inside of Oracle Cloud.
|
||||
OracleUserDataEndpoint = "http://169.254.169.254/opc/v2/instance/metadata/user_data"
|
||||
// OracleNetworkEndpoint is the local network metadata endpoint inside of Oracle Cloud.
|
||||
OracleNetworkEndpoint = "http://169.254.169.254/opc/v2/vnics/"
|
||||
)
|
||||
|
||||
// NetworkConfig holds network interface meta config.
|
||||
type NetworkConfig struct {
|
||||
HWAddr string `json:"macAddr"`
|
||||
PrivateIP string `json:"privateIp"`
|
||||
VirtualRouterIP string `json:"virtualRouterIp"`
|
||||
SubnetCidrBlock string `json:"subnetCidrBlock"`
|
||||
Ipv6SubnetCidrBlock string `json:"ipv6SubnetCidrBlock,omitempty"`
|
||||
Ipv6VirtualRouterIP string `json:"ipv6VirtualRouterIp,omitempty"`
|
||||
}
|
||||
|
||||
// Oracle is the concrete type that implements the platform.Platform interface.
|
||||
type Oracle struct{}
|
||||
|
||||
// Name implements the platform.Platform interface.
|
||||
func (o *Oracle) Name() string {
|
||||
return "oracle"
|
||||
}
|
||||
|
||||
// ConfigurationNetwork implements the network configuration interface.
|
||||
func (o *Oracle) ConfigurationNetwork(metadataNetworkConfig []byte, confProvider config.Provider) (config.Provider, error) {
|
||||
var machineConfig *v1alpha1.Config
|
||||
|
||||
machineConfig, ok := confProvider.(*v1alpha1.Config)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unable to determine machine config type")
|
||||
}
|
||||
|
||||
if machineConfig.MachineConfig == nil {
|
||||
machineConfig.MachineConfig = &v1alpha1.MachineConfig{}
|
||||
}
|
||||
|
||||
if machineConfig.MachineConfig.MachineNetwork == nil {
|
||||
machineConfig.MachineConfig.MachineNetwork = &v1alpha1.NetworkConfig{}
|
||||
}
|
||||
|
||||
var interfaceAddresses []NetworkConfig
|
||||
|
||||
if err := json.Unmarshal(metadataNetworkConfig, &interfaceAddresses); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if machineConfig.MachineConfig.MachineNetwork.NetworkInterfaces == nil {
|
||||
for idx, iface := range interfaceAddresses {
|
||||
ipv6 := iface.Ipv6SubnetCidrBlock != "" && iface.Ipv6VirtualRouterIP != ""
|
||||
|
||||
if ipv6 {
|
||||
device := &v1alpha1.Device{
|
||||
DeviceInterface: fmt.Sprintf("eth%d", idx),
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{DHCPIPv6: pointer.ToBool(true)},
|
||||
}
|
||||
|
||||
machineConfig.MachineConfig.MachineNetwork.NetworkInterfaces = append(machineConfig.MachineConfig.MachineNetwork.NetworkInterfaces, device)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return confProvider, nil
|
||||
}
|
||||
|
||||
// Configuration implements the platform.Platform interface.
|
||||
func (o *Oracle) Configuration(ctx context.Context) ([]byte, error) {
|
||||
log.Printf("fetching network config from %q", OracleNetworkEndpoint)
|
||||
|
||||
metadataNetworkConfig, err := download.Download(ctx, OracleNetworkEndpoint,
|
||||
download.WithHeaders(map[string]string{"Authorization": "Bearer Oracle"}))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch network config from metadata service")
|
||||
}
|
||||
|
||||
log.Printf("fetching machine config from: %q", OracleUserDataEndpoint)
|
||||
|
||||
machineConfigDl, err := download.Download(ctx, OracleUserDataEndpoint,
|
||||
download.WithHeaders(map[string]string{"Authorization": "Bearer Oracle"}),
|
||||
download.WithErrorOnNotFound(errors.ErrNoConfigSource),
|
||||
download.WithErrorOnEmptyResponse(errors.ErrNoConfigSource))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
machineConfig, err := base64.StdEncoding.DecodeString(string(machineConfigDl))
|
||||
if err != nil {
|
||||
return nil, errors.ErrNoConfigSource
|
||||
}
|
||||
|
||||
confProvider, err := configloader.NewFromBytes(machineConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error parsing machine config: %w", err)
|
||||
}
|
||||
|
||||
confProvider, err = o.ConfigurationNetwork(metadataNetworkConfig, confProvider)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return confProvider.Bytes()
|
||||
}
|
||||
|
||||
// Hostname implements the platform.Platform interface.
|
||||
func (o *Oracle) Hostname(ctx context.Context) (hostname []byte, err error) {
|
||||
log.Printf("fetching hostname from: %q", OracleHostnameEndpoint)
|
||||
|
||||
hostname, err = download.Download(ctx, OracleHostnameEndpoint,
|
||||
download.WithHeaders(map[string]string{"Authorization": "Bearer Oracle"}),
|
||||
download.WithErrorOnNotFound(errors.ErrNoHostname),
|
||||
download.WithErrorOnEmptyResponse(errors.ErrNoHostname))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return hostname, nil
|
||||
}
|
||||
|
||||
// Mode implements the platform.Platform interface.
|
||||
func (o *Oracle) Mode() runtime.Mode {
|
||||
return runtime.ModeCloud
|
||||
}
|
||||
|
||||
// ExternalIPs implements the runtime.Platform interface.
|
||||
func (o *Oracle) ExternalIPs(ctx context.Context) (addrs []net.IP, err error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// KernelArgs implements the runtime.Platform interface.
|
||||
func (o *Oracle) KernelArgs() procfs.Parameters {
|
||||
return []*procfs.Parameter{
|
||||
procfs.NewParameter("console").Append("tty1").Append("ttyS0"),
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package oracle_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/AlekSi/pointer"
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/oracle"
|
||||
"github.com/talos-systems/talos/pkg/machinery/config/types/v1alpha1"
|
||||
)
|
||||
|
||||
type ConfigSuite struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func (suite *ConfigSuite) TestNetworkConfig() {
|
||||
cfg := []byte(`
|
||||
[ {
|
||||
"vnicId" : "ocid1.vnic.oc1.eu-amsterdam-1.asdasd",
|
||||
"privateIp" : "172.16.1.11",
|
||||
"vlanTag" : 1,
|
||||
"macAddr" : "02:00:17:00:00:00",
|
||||
"virtualRouterIp" : "172.16.1.1",
|
||||
"subnetCidrBlock" : "172.16.1.0/24",
|
||||
"ipv6SubnetCidrBlock" : "2603:a:b:c::/64",
|
||||
"ipv6VirtualRouterIp" : "fe80::a:b:c:d"
|
||||
} ]
|
||||
`)
|
||||
a := &oracle.Oracle{}
|
||||
|
||||
defaultMachineConfig := &v1alpha1.Config{}
|
||||
|
||||
machineConfig := &v1alpha1.Config{
|
||||
MachineConfig: &v1alpha1.MachineConfig{
|
||||
MachineNetwork: &v1alpha1.NetworkConfig{
|
||||
NetworkInterfaces: []*v1alpha1.Device{
|
||||
{
|
||||
DeviceInterface: "eth0",
|
||||
DeviceDHCP: true,
|
||||
DeviceDHCPOptions: &v1alpha1.DHCPOptions{DHCPIPv6: pointer.ToBool(true)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := a.ConfigurationNetwork(cfg, defaultMachineConfig)
|
||||
|
||||
suite.Require().NoError(err)
|
||||
suite.Assert().Equal(machineConfig, result)
|
||||
}
|
||||
|
||||
func TestConfigSuite(t *testing.T) {
|
||||
suite.Run(t, new(ConfigSuite))
|
||||
}
|
@ -21,6 +21,7 @@ import (
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/metal"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/nocloud"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/openstack"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/oracle"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/packet"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/scaleway"
|
||||
"github.com/talos-systems/talos/internal/app/machined/pkg/runtime/v1alpha1/platform/upcloud"
|
||||
@ -72,6 +73,8 @@ func newPlatform(platform string) (p runtime.Platform, err error) {
|
||||
p = &metal.Metal{}
|
||||
case "openstack":
|
||||
p = &openstack.Openstack{}
|
||||
case "oracle":
|
||||
p = &oracle.Oracle{}
|
||||
case "nocloud":
|
||||
p = &nocloud.Nocloud{}
|
||||
case "packet":
|
||||
|
105
website/content/docs/v0.15/Cloud Platforms/oracle.md
Normal file
105
website/content/docs/v0.15/Cloud Platforms/oracle.md
Normal file
@ -0,0 +1,105 @@
|
||||
---
|
||||
title: "Oracle"
|
||||
description: "Creating a cluster via the CLI (oci) on OracleCloud.com."
|
||||
---
|
||||
|
||||
## Upload image
|
||||
|
||||
Oracle Cloud at the moment does not have a Talos official image.
|
||||
So you can use [Bring Your Own Image (BYOI)](https://docs.oracle.com/en-us/iaas/Content/Compute/References/bringyourownimage.htm) approach.
|
||||
|
||||
Once the image is uploaded, set the ```Boot volume type``` to ``Paravirtualized`` mode.
|
||||
|
||||
OracleCloud has highly available NTP service, it can be enabled in Talos machine config with:
|
||||
|
||||
```yaml
|
||||
machine:
|
||||
time:
|
||||
servers:
|
||||
- 169.254.169.254
|
||||
```
|
||||
|
||||
## Creating a Cluster via the CLI
|
||||
|
||||
```bash
|
||||
```
|
||||
|
||||
### Create a Load Balancer
|
||||
|
||||
Create a load balancer by issuing the commands shown below.
|
||||
Save the IP/DNS name, as this info will be used in the next step.
|
||||
|
||||
```bash
|
||||
```
|
||||
|
||||
### Create the Machine Configuration Files
|
||||
|
||||
#### Generating Base Configurations
|
||||
|
||||
Using the IP/DNS name of the loadbalancer created earlier, generate the base configuration files for the Talos machines by issuing:
|
||||
|
||||
```bash
|
||||
$ talosctl gen config talos-k8s-oracle-tutorial https://<load balancer IP or DNS>:6443
|
||||
created controlplane.yaml
|
||||
created worker.yaml
|
||||
created talosconfig
|
||||
```
|
||||
|
||||
At this point, you can modify the generated configs to your liking.
|
||||
Optionally, you can specify `--config-patch` with RFC6902 jsonpatches which will be applied during the config generation.
|
||||
|
||||
#### Validate the Configuration Files
|
||||
|
||||
Validate any edited machine configs with:
|
||||
|
||||
```bash
|
||||
$ talosctl validate --config controlplane.yaml --mode cloud
|
||||
controlplane.yaml is valid for cloud mode
|
||||
$ talosctl validate --config worker.yaml --mode cloud
|
||||
worker.yaml is valid for cloud mode
|
||||
```
|
||||
|
||||
### Create the Servers
|
||||
|
||||
#### Create the Control Plane Nodes
|
||||
|
||||
Create the control plane nodes with:
|
||||
|
||||
```bash
|
||||
```
|
||||
|
||||
#### Create the Worker Nodes
|
||||
|
||||
Create the worker nodes with the following command, repeating (and incrementing the name counter) as many times as desired.
|
||||
|
||||
```bash
|
||||
```
|
||||
|
||||
### Bootstrap Etcd
|
||||
|
||||
To configure `talosctl` we will need the first control plane node's IP.
|
||||
This can be found by issuing:
|
||||
|
||||
```bash
|
||||
```
|
||||
|
||||
Set the `endpoints` and `nodes` for your talosconfig with:
|
||||
|
||||
```bash
|
||||
talosctl --talosconfig talosconfig config endpoint <control-plane-1-IP>
|
||||
talosctl --talosconfig talosconfig config node <control-plane-1-IP>
|
||||
```
|
||||
|
||||
Bootstrap `etcd` on the first control plane node with:
|
||||
|
||||
```bash
|
||||
talosctl --talosconfig talosconfig bootstrap
|
||||
```
|
||||
|
||||
### Retrieve the `kubeconfig`
|
||||
|
||||
At this point we can retrieve the admin `kubeconfig` by running:
|
||||
|
||||
```bash
|
||||
talosctl --talosconfig talosconfig kubeconfig .
|
||||
```
|
@ -11,7 +11,7 @@ weight: 6
|
||||
| Kubernetes | 1.23, 1.22, 1.21 | 1.23, 1.22, 1.21 |
|
||||
| Architecture | amd64, arm64 |
|
||||
| **Platforms** | | |
|
||||
| - cloud | AWS, GCP, Azure, Digital Ocean, Hetzner, OpenStack, Scaleway, Vultr, Upcloud |
|
||||
| - cloud | AWS, GCP, Azure, Digital Ocean, Hetzner, OpenStack, Oracle Cloud, Scaleway, Vultr, Upcloud | AWS, GCP, Azure, Digital Ocean, Hetzner, OpenStack, Scaleway, Vultr, Upcloud |
|
||||
| - bare metal | x86: BIOS, UEFI; arm64: UEFI; boot: ISO, PXE, disk image |
|
||||
| - virtualized | VMware, Hyper-V, KVM, Proxmox, Xen |
|
||||
| - SBCs | Raspberry Pi4, Banana Pi M64, Pine64, and other |
|
||||
@ -46,6 +46,7 @@ Tier 3: Not tested by core Talos team, community tested.
|
||||
|
||||
* Hetzner
|
||||
* nocloud
|
||||
* Oracle Cloud
|
||||
* Scaleway
|
||||
* Vultr
|
||||
* Upcloud
|
||||
|
Loading…
Reference in New Issue
Block a user