mirror of https://github.com/kubernetes/kops.git
hetzner: Create cluster without DNS or Gossip
This commit is contained in:
parent
ad9c9fcad8
commit
4e5ded6dc3
|
@ -337,9 +337,10 @@ func NewCmdCreateCluster(f *util.Factory, out io.Writer) *cobra.Command {
|
|||
})
|
||||
|
||||
// DNS
|
||||
cmd.Flags().StringVar(&options.DNSType, "dns", options.DNSType, "DNS type to use: public or private")
|
||||
supportedDnsTypes := []string{"public", "private", "none"}
|
||||
cmd.Flags().StringVar(&options.DNSType, "dns", options.DNSType, "DNS type to use: "+strings.Join(supportedDnsTypes, ", "))
|
||||
cmd.RegisterFlagCompletionFunc("dns", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
return []string{"public", "private"}, cobra.ShellCompDirectiveNoFileComp
|
||||
return supportedDnsTypes, cobra.ShellCompDirectiveNoFileComp
|
||||
})
|
||||
|
||||
// Bastion
|
||||
|
|
|
@ -276,7 +276,7 @@ func TestMinimal_v1_26(t *testing.T) {
|
|||
// TestHetzner runs the test on a minimum configuration
|
||||
func TestHetzner(t *testing.T) {
|
||||
t.Setenv("HCLOUD_TOKEN", "REDACTED")
|
||||
newIntegrationTest("minimal.k8s.local", "minimal_hetzner").
|
||||
newIntegrationTest("minimal.example.com", "minimal_hetzner").
|
||||
runTestTerraformHetzner(t)
|
||||
}
|
||||
|
||||
|
@ -1462,7 +1462,6 @@ func (i *integrationTest) runTestTerraformHetzner(t *testing.T) {
|
|||
"aws_s3_object_nodeupconfig-nodes-fsn1_content",
|
||||
"aws_s3_object_"+i.clusterName+"-addons-bootstrap_content",
|
||||
"aws_s3_object_"+i.clusterName+"-addons-coredns.addons.k8s.io-k8s-1.12_content",
|
||||
"aws_s3_object_"+i.clusterName+"-addons-dns-controller.addons.k8s.io-k8s-1.12_content",
|
||||
"aws_s3_object_"+i.clusterName+"-addons-hcloud-cloud-controller.addons.k8s.io-k8s-1.22_content",
|
||||
"aws_s3_object_"+i.clusterName+"-addons-hcloud-csi-driver.addons.k8s.io-k8s-1.22_content",
|
||||
"aws_s3_object_"+i.clusterName+"-addons-kops-controller.addons.k8s.io-k8s-1.16_content",
|
||||
|
|
|
@ -77,7 +77,7 @@ kops create cluster [CLUSTER] [flags]
|
|||
--container-runtime string Container runtime to use: containerd, docker
|
||||
--disable-subnet-tags Disable automatic subnet tagging
|
||||
--discovery-store string A public location where we publish OIDC-compatible discovery information under a cluster-specific directory. Enables IRSA in AWS.
|
||||
--dns string DNS type to use: public or private (default "Public")
|
||||
--dns string DNS type to use: public, private, none
|
||||
--dns-zone string DNS hosted zone (defaults to longest matching zone)
|
||||
--dry-run If true, only print the object that would be sent, without sending it. This flag can be used to create a cluster YAML or JSON manifest.
|
||||
--encrypt-etcd-storage Generate key in AWS KMS and use it for encrypt etcd volumes
|
||||
|
|
|
@ -30,32 +30,31 @@ var _ fi.ModelBuilder = &EtcHostsBuilder{}
|
|||
|
||||
// Build is responsible for configuring the gossip DNS tasks.
|
||||
func (b *EtcHostsBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||
useGossip := b.Cluster.IsGossip()
|
||||
if !useGossip {
|
||||
return nil
|
||||
|
||||
task := &nodetasks.UpdateEtcHostsTask{
|
||||
Name: "control-plane-address",
|
||||
}
|
||||
|
||||
if b.IsMaster {
|
||||
task := &nodetasks.UpdateEtcHostsTask{
|
||||
Name: "control-plane-bootstrap",
|
||||
}
|
||||
|
||||
if b.Cluster.Spec.MasterInternalName != "" {
|
||||
task.Records = append(task.Records, nodetasks.HostRecord{
|
||||
Hostname: b.Cluster.Spec.MasterInternalName,
|
||||
Addresses: []string{"127.0.0.1"},
|
||||
})
|
||||
}
|
||||
if b.IsMaster && b.Cluster.IsGossip() {
|
||||
task.Records = append(task.Records, nodetasks.HostRecord{
|
||||
Hostname: b.Cluster.Spec.MasterInternalName,
|
||||
Addresses: []string{"127.0.0.1"},
|
||||
})
|
||||
if b.Cluster.Spec.MasterPublicName != "" {
|
||||
task.Records = append(task.Records, nodetasks.HostRecord{
|
||||
Hostname: b.Cluster.Spec.MasterPublicName,
|
||||
Addresses: []string{"127.0.0.1"},
|
||||
})
|
||||
}
|
||||
} else if b.Cluster.UsesNoneDNS() {
|
||||
task.Records = append(task.Records, nodetasks.HostRecord{
|
||||
Hostname: b.Cluster.Spec.MasterInternalName,
|
||||
Addresses: []string{b.BootConfig.APIServer},
|
||||
})
|
||||
}
|
||||
|
||||
if len(task.Records) != 0 {
|
||||
c.AddTask(task)
|
||||
}
|
||||
if len(task.Records) != 0 {
|
||||
c.AddTask(task)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -367,7 +367,9 @@ func (b *KubeAPIServerBuilder) writeServerCertificate(c *fi.ModelBuilderContext,
|
|||
}
|
||||
|
||||
// Names specified in the cluster spec
|
||||
alternateNames = append(alternateNames, b.Cluster.Spec.MasterPublicName)
|
||||
if b.Cluster.Spec.MasterPublicName != "" {
|
||||
alternateNames = append(alternateNames, b.Cluster.Spec.MasterPublicName)
|
||||
}
|
||||
alternateNames = append(alternateNames, b.Cluster.Spec.MasterInternalName)
|
||||
alternateNames = append(alternateNames, b.Cluster.Spec.AdditionalSANs...)
|
||||
|
||||
|
@ -726,12 +728,16 @@ func (b *KubeAPIServerBuilder) buildAnnotations() map[string]string {
|
|||
annotations := make(map[string]string)
|
||||
annotations["kubectl.kubernetes.io/default-container"] = "kube-apiserver"
|
||||
|
||||
if b.Cluster.UsesNoneDNS() {
|
||||
return annotations
|
||||
}
|
||||
|
||||
if b.Cluster.Spec.API != nil {
|
||||
if b.Cluster.Spec.API.LoadBalancer == nil || !b.Cluster.Spec.API.LoadBalancer.UseForInternalAPI {
|
||||
annotations["dns.alpha.kubernetes.io/internal"] = b.Cluster.Spec.MasterInternalName
|
||||
}
|
||||
|
||||
if b.Cluster.Spec.API.DNS != nil {
|
||||
if b.Cluster.Spec.API.DNS != nil && b.Cluster.Spec.MasterPublicName != "" {
|
||||
annotations["dns.alpha.kubernetes.io/external"] = b.Cluster.Spec.MasterPublicName
|
||||
}
|
||||
}
|
||||
|
|
|
@ -807,10 +807,6 @@ func (c *Cluster) FillDefaults() error {
|
|||
c.Spec.MasterInternalName = "api.internal." + c.ObjectMeta.Name
|
||||
}
|
||||
|
||||
if c.Spec.MasterPublicName == "" {
|
||||
c.Spec.MasterPublicName = "api." + c.ObjectMeta.Name
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -903,6 +899,27 @@ func (c *Cluster) IsGossip() bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func (c *Cluster) UsesPublicDNS() bool {
|
||||
if c.Spec.Topology == nil || c.Spec.Topology.DNS == nil || c.Spec.Topology.DNS.Type == DNSTypePublic {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Cluster) UsesPrivateDNS() bool {
|
||||
if c.Spec.Topology != nil && c.Spec.Topology.DNS != nil && c.Spec.Topology.DNS.Type == DNSTypePrivate {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *Cluster) UsesNoneDNS() bool {
|
||||
if c.Spec.Topology != nil && c.Spec.Topology.DNS != nil && c.Spec.Topology.DNS.Type == DNSTypeNone {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *ClusterSpec) IsIPv6Only() bool {
|
||||
return utils.IsIPv6CIDR(c.NonMasqueradeCIDR)
|
||||
}
|
||||
|
|
|
@ -29,6 +29,7 @@ var SupportedTopologies = []string{
|
|||
var SupportedDnsTypes = []string{
|
||||
string(DNSTypePublic),
|
||||
string(DNSTypePrivate),
|
||||
string(DNSTypeNone),
|
||||
}
|
||||
|
||||
type TopologySpec struct {
|
||||
|
@ -58,4 +59,5 @@ type DNSType string
|
|||
const (
|
||||
DNSTypePublic DNSType = "Public"
|
||||
DNSTypePrivate DNSType = "Private"
|
||||
DNSTypeNone DNSType = "None"
|
||||
)
|
||||
|
|
|
@ -429,6 +429,9 @@ func validateTopology(c *kops.Cluster, topology *kops.TopologySpec, fieldPath *f
|
|||
if topology.DNS != nil {
|
||||
value := string(topology.DNS.Type)
|
||||
allErrs = append(allErrs, IsValidValue(fieldPath.Child("dns", "type"), &value, kops.SupportedDnsTypes)...)
|
||||
if value == string(kops.DNSTypeNone) && c.Spec.GetCloudProvider() != kops.CloudProviderHetzner {
|
||||
allErrs = append(allErrs, field.Invalid(fieldPath.Child("dns", "type"), &value, fmt.Sprintf("not supported for %q", c.Spec.GetCloudProvider())))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
|
@ -1613,8 +1616,8 @@ func validateExternalDNS(cluster *kops.Cluster, spec *kops.ExternalDNSConfig, fl
|
|||
}
|
||||
|
||||
if spec.Provider == kops.ExternalDNSProviderExternalDNS {
|
||||
if cluster.IsGossip() {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("provider"), "external-dns does not support gossip clusters"))
|
||||
if cluster.IsGossip() || cluster.UsesNoneDNS() {
|
||||
allErrs = append(allErrs, field.Forbidden(fldPath.Child("provider"), "external-dns requires public or private DNS topology"))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,8 @@ type BootConfig struct {
|
|||
ConfigBase *string `json:",omitempty"`
|
||||
// ConfigServer holds the configuration for the configuration server.
|
||||
ConfigServer *ConfigServerOptions `json:",omitempty"`
|
||||
// APIServer is the API server IP address.
|
||||
APIServer string `json:",omitempty"`
|
||||
// InstanceGroupName is the name of the instance group.
|
||||
InstanceGroupName string `json:",omitempty"`
|
||||
// InstanceGroupRole is the instance group role.
|
||||
|
|
|
@ -58,6 +58,11 @@ func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.Se
|
|||
useELBName = true
|
||||
}
|
||||
|
||||
// If the cluster has DNS disabled, must use the load balancer name
|
||||
if cluster.UsesNoneDNS() {
|
||||
useELBName = true
|
||||
}
|
||||
|
||||
// If the DNS is set up as a private HostedZone, but here we have to be
|
||||
// careful that we aren't accessing the API over DirectConnect (or a VPN).
|
||||
// We differentiate using the heuristic that if we have an internal ELB
|
||||
|
@ -86,7 +91,7 @@ func BuildKubecfg(cluster *kops.Cluster, keyStore fi.Keystore, secretStore fi.Se
|
|||
|
||||
sort.Strings(targets)
|
||||
if len(targets) == 0 {
|
||||
klog.Warningf("Did not find API endpoint for gossip hostname; may not be able to reach cluster")
|
||||
klog.Warningf("Did not find API endpoint; may not be able to reach cluster")
|
||||
} else {
|
||||
if len(targets) != 1 {
|
||||
klog.Warningf("Found multiple API endpoints (%v), choosing arbitrarily", targets)
|
||||
|
|
|
@ -519,7 +519,7 @@ func (b *APILoadBalancerBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
}
|
||||
}
|
||||
|
||||
if b.Cluster.IsGossip() || b.UsePrivateDNS() {
|
||||
if b.Cluster.IsGossip() || b.Cluster.UsesPrivateDNS() || b.Cluster.UsesNoneDNS() {
|
||||
// Ensure the LB hostname is included in the TLS certificate,
|
||||
// if we're not going to use an alias for it
|
||||
clb.ForAPIServer = true
|
||||
|
|
|
@ -34,7 +34,7 @@ type DNSModelBuilder struct {
|
|||
var _ fi.ModelBuilder = &DNSModelBuilder{}
|
||||
|
||||
func (b *DNSModelBuilder) ensureDNSZone(c *fi.ModelBuilderContext) error {
|
||||
if b.Cluster.IsGossip() {
|
||||
if b.Cluster.IsGossip() || b.Cluster.UsesNoneDNS() {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -72,22 +72,10 @@ func (b *DNSModelBuilder) ensureDNSZone(c *fi.ModelBuilderContext) error {
|
|||
|
||||
func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
||||
// Add a HostedZone if we are going to publish a dns record that depends on it
|
||||
if b.UsePrivateDNS() {
|
||||
// Check to see if we are using a bastion DNS record that points to the hosted zone
|
||||
// If we are, we need to make sure we include the hosted zone as a task
|
||||
|
||||
if !b.Cluster.IsGossip() && !b.Cluster.UsesNoneDNS() {
|
||||
if err := b.ensureDNSZone(c); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// We now create the DNS Zone for AWS even in the case of public zones;
|
||||
// it has to exist for the IAM record anyway.
|
||||
// TODO: We can now rationalize the code paths
|
||||
if !b.Cluster.IsGossip() {
|
||||
if err := b.ensureDNSZone(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var targetLoadBalancer awstasks.DNSTarget
|
||||
|
@ -106,7 +94,7 @@ func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
// This will point our external DNS record to the load balancer, and put the
|
||||
// pieces together for kubectl to work
|
||||
|
||||
if !b.Cluster.IsGossip() {
|
||||
if !b.Cluster.IsGossip() && !b.Cluster.UsesNoneDNS() {
|
||||
if err := b.ensureDNSZone(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -136,7 +124,7 @@ func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
// This will point the internal API DNS record to the load balancer.
|
||||
// This means kubelet connections go via the load balancer and are more HA.
|
||||
|
||||
if !b.Cluster.IsGossip() {
|
||||
if !b.Cluster.IsGossip() && !b.Cluster.UsesNoneDNS() {
|
||||
if err := b.ensureDNSZone(c); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -176,8 +164,10 @@ func (b *DNSModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
// is similar to others, but I would like to keep it on it's own in case we need
|
||||
// to change anything.
|
||||
|
||||
if err := b.ensureDNSZone(c); err != nil {
|
||||
return err
|
||||
if !b.Cluster.IsGossip() && !b.Cluster.UsesNoneDNS() {
|
||||
if err := b.ensureDNSZone(c); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -236,7 +236,7 @@ func (b *IAMModelBuilder) buildIAMRolePolicy(role iam.Subject, iamName string, i
|
|||
},
|
||||
}
|
||||
|
||||
if !b.Cluster.IsGossip() {
|
||||
if !b.Cluster.IsGossip() && !b.Cluster.UsesNoneDNS() {
|
||||
// This is slightly tricky; we need to know the hosted zone id,
|
||||
// but we might be creating the hosted zone dynamically.
|
||||
// We create a stub-reference which will be combined by the execution engine.
|
||||
|
|
|
@ -80,7 +80,7 @@ func (b *APILoadBalancerModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
|
||||
c.AddTask(lb)
|
||||
|
||||
if b.Cluster.IsGossip() || b.UsePrivateDNS() {
|
||||
if b.Cluster.IsGossip() || b.Cluster.UsesPrivateDNS() || b.Cluster.UsesNoneDNS() {
|
||||
lb.ForAPIServer = true
|
||||
}
|
||||
|
||||
|
|
|
@ -182,7 +182,7 @@ func (b *BootstrapScript) buildEnvironmentVariables(cluster *kops.Cluster) (map[
|
|||
}
|
||||
}
|
||||
|
||||
if cluster.Spec.GetCloudProvider() == kops.CloudProviderHetzner {
|
||||
if cluster.Spec.GetCloudProvider() == kops.CloudProviderHetzner && (b.ig.IsMaster() || cluster.IsGossip()) {
|
||||
hcloudToken := os.Getenv("HCLOUD_TOKEN")
|
||||
if hcloudToken != "" {
|
||||
env["HCLOUD_TOKEN"] = hcloudToken
|
||||
|
|
|
@ -44,13 +44,5 @@ func (b *DefaultsOptionsBuilder) BuildOptions(o interface{}) error {
|
|||
}
|
||||
}
|
||||
|
||||
if options.ExternalDNS == nil {
|
||||
options.ExternalDNS = &kops.ExternalDNSConfig{}
|
||||
}
|
||||
|
||||
if options.ExternalDNS.Provider == "" {
|
||||
options.ExternalDNS.Provider = kops.ExternalDNSProviderDNSController
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ func (b *DiscoveryOptionsBuilder) BuildOptions(o interface{}) error {
|
|||
return fmt.Errorf("locationStore=%q is of unexpected type %T", store, base)
|
||||
}
|
||||
} else {
|
||||
if supportsPublicJWKS(clusterSpec) {
|
||||
if supportsPublicJWKS(clusterSpec) && clusterSpec.MasterPublicName != "" {
|
||||
serviceAccountIssuer = "https://" + clusterSpec.MasterPublicName
|
||||
} else {
|
||||
serviceAccountIssuer = "https://" + clusterSpec.MasterInternalName
|
||||
|
|
|
@ -292,25 +292,6 @@ func (b *KopsModelContext) APILoadBalancerClass() kops.LoadBalancerClass {
|
|||
return kops.LoadBalancerClassClassic
|
||||
}
|
||||
|
||||
// UsePrivateDNS checks if we are using private DNS
|
||||
func (b *KopsModelContext) UsePrivateDNS() bool {
|
||||
topology := b.Cluster.Spec.Topology
|
||||
if topology != nil && topology.DNS != nil {
|
||||
switch topology.DNS.Type {
|
||||
case kops.DNSTypePublic:
|
||||
return false
|
||||
case kops.DNSTypePrivate:
|
||||
return true
|
||||
|
||||
default:
|
||||
klog.Warningf("Unknown DNS type %q", topology.DNS.Type)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// UseClassicLoadBalancer checks if we are using Classic LoadBalancer
|
||||
func (b *KopsModelContext) UseClassicLoadBalancer() bool {
|
||||
return b.Cluster.Spec.API.LoadBalancer.Class == kops.LoadBalancerClassClassic
|
||||
|
|
|
@ -77,7 +77,7 @@ func (b *APILoadBalancerModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
c.AddTask(loadbalancer)
|
||||
|
||||
// Temporarily do not know the role of the following function
|
||||
if b.Cluster.IsGossip() || b.UsePrivateDNS() {
|
||||
if b.Cluster.IsGossip() || b.Cluster.UsesPrivateDNS() || b.Cluster.UsesNoneDNS() {
|
||||
// Ensure the LB hostname is included in the TLS certificate,
|
||||
// if we're not going to use an alias for it
|
||||
loadbalancer.ForAPIServer = true
|
||||
|
|
|
@ -304,7 +304,7 @@ func (b *ServerGroupModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
}
|
||||
c.AddTask(lbfipTask)
|
||||
|
||||
if b.Cluster.IsGossip() || b.UsePrivateDNS() {
|
||||
if b.Cluster.IsGossip() || b.Cluster.UsesPrivateDNS() || b.Cluster.UsesNoneDNS() {
|
||||
b.associateFIPToKeypair(lbfipTask)
|
||||
}
|
||||
|
||||
|
|
|
@ -113,7 +113,9 @@ func (b *PKIModelBuilder) Build(c *fi.ModelBuilderContext) error {
|
|||
"localhost",
|
||||
serviceName,
|
||||
strings.Join([]string{serviceName, b.Cluster.Name}, "."),
|
||||
strings.Join([]string{serviceName, b.Cluster.Spec.DNSZone}, "."),
|
||||
}
|
||||
if b.Cluster.Spec.DNSZone != "" {
|
||||
alternateNames = append(alternateNames, strings.Join([]string{serviceName, b.Cluster.Spec.DNSZone}, "."))
|
||||
}
|
||||
|
||||
// @note: the certificate used by the node authorizers
|
||||
|
|
|
@ -124,16 +124,15 @@ func NewClusterValidator(cluster *kops.Cluster, cloud fi.Cloud, instanceGroupLis
|
|||
func (v *clusterValidatorImpl) Validate() (*ValidationCluster, error) {
|
||||
ctx := context.TODO()
|
||||
|
||||
clusterName := v.cluster.Name
|
||||
dnsProvider := kops.ExternalDNSProviderDNSController
|
||||
if v.cluster.Spec.ExternalDNS != nil && v.cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderExternalDNS {
|
||||
dnsProvider = kops.ExternalDNSProviderExternalDNS
|
||||
}
|
||||
|
||||
validation := &ValidationCluster{}
|
||||
|
||||
// Do not use if we are running gossip
|
||||
if !v.cluster.IsGossip() {
|
||||
// Do not use if we are running gossip or without dns
|
||||
if !v.cluster.IsGossip() && !v.cluster.UsesNoneDNS() {
|
||||
dnsProvider := kops.ExternalDNSProviderDNSController
|
||||
if v.cluster.Spec.ExternalDNS != nil && v.cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderExternalDNS {
|
||||
dnsProvider = kops.ExternalDNSProviderExternalDNS
|
||||
}
|
||||
|
||||
hasPlaceHolderIPAddress, err := hasPlaceHolderIP(v.host)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -168,7 +167,7 @@ func (v *clusterValidatorImpl) Validate() (*ValidationCluster, error) {
|
|||
readyNodes, nodeInstanceGroupMapping := validation.validateNodes(cloudGroups, v.instanceGroups)
|
||||
|
||||
if err := validation.collectPodFailures(ctx, v.k8sClient, readyNodes, nodeInstanceGroupMapping); err != nil {
|
||||
return nil, fmt.Errorf("cannot get pod health for %q: %v", clusterName, err)
|
||||
return nil, fmt.Errorf("cannot get pod health for %q: %v", v.cluster.Name, err)
|
||||
}
|
||||
|
||||
return validation, nil
|
||||
|
|
|
@ -301,7 +301,7 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
|
|||
if cluster.Spec.KubernetesVersion == "" {
|
||||
return fmt.Errorf("KubernetesVersion not set")
|
||||
}
|
||||
if cluster.Spec.DNSZone == "" && !cluster.IsGossip() {
|
||||
if cluster.Spec.DNSZone == "" && !cluster.IsGossip() && !cluster.UsesNoneDNS() {
|
||||
return fmt.Errorf("DNSZone not set")
|
||||
}
|
||||
|
||||
|
@ -482,9 +482,7 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
|
|||
modelContext.SSHPublicKeys = sshPublicKeys
|
||||
modelContext.Region = cloud.Region()
|
||||
|
||||
if cluster.IsGossip() {
|
||||
klog.V(2).Infof("Gossip DNS: skipping DNS validation")
|
||||
} else {
|
||||
if !cluster.IsGossip() && !cluster.UsesNoneDNS() {
|
||||
err = validateDNS(cluster, cloud)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -791,7 +789,7 @@ func (c *ApplyClusterCmd) Run(ctx context.Context) error {
|
|||
return fmt.Errorf("error running tasks: %v", err)
|
||||
}
|
||||
|
||||
if cluster.IsGossip() {
|
||||
if cluster.IsGossip() || cluster.UsesNoneDNS() {
|
||||
shouldPrecreateDNS = false
|
||||
}
|
||||
|
||||
|
@ -1417,6 +1415,25 @@ func (n *nodeUpConfigBuilder) BuildConfig(ig *kops.InstanceGroup, apiserverAddit
|
|||
config.ApiserverAdditionalIPs = apiserverAdditionalIPs
|
||||
}
|
||||
|
||||
// Set API server address to an IP from the cluster network CIDR
|
||||
if cluster.UsesNoneDNS() {
|
||||
for _, networkCIDR := range append(cluster.Spec.AdditionalNetworkCIDRs, cluster.Spec.NetworkCIDR) {
|
||||
_, cidr, err := net.ParseCIDR(networkCIDR)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to parse network CIDR %q: %w", networkCIDR, err)
|
||||
}
|
||||
for _, additionalIP := range apiserverAdditionalIPs {
|
||||
if cidr.Contains(net.ParseIP(additionalIP)) {
|
||||
bootConfig.APIServer = additionalIP
|
||||
break
|
||||
}
|
||||
}
|
||||
if bootConfig.APIServer != "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for _, manifest := range n.assetBuilder.StaticManifests {
|
||||
match := false
|
||||
for _, r := range manifest.Roles {
|
||||
|
|
|
@ -486,32 +486,12 @@ func (b *BootstrapChannelBuilder) buildAddons(c *fi.ModelBuilderContext) (*Addon
|
|||
})
|
||||
}
|
||||
|
||||
if b.Cluster.Spec.ExternalDNS == nil || b.Cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderDNSController {
|
||||
{
|
||||
key := "dns-controller.addons.k8s.io"
|
||||
location := key + "/k8s-1.12.yaml"
|
||||
id := "k8s-1.12"
|
||||
|
||||
addons.Add(&channelsapi.AddonSpec{
|
||||
Name: fi.String(key),
|
||||
Selector: map[string]string{"k8s-addon": key},
|
||||
Manifest: fi.String(location),
|
||||
Id: id,
|
||||
})
|
||||
}
|
||||
|
||||
// Generate dns-controller ServiceAccount IAM permissions.
|
||||
// Gossip clsuters do not require any cloud permissions.
|
||||
if b.UseServiceAccountExternalPermissions() && !b.Cluster.IsGossip() {
|
||||
serviceAccountRoles = append(serviceAccountRoles, &dnscontroller.ServiceAccount{})
|
||||
}
|
||||
} else if b.Cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderExternalDNS {
|
||||
{
|
||||
key := "external-dns.addons.k8s.io"
|
||||
|
||||
if !b.Cluster.UsesNoneDNS() {
|
||||
if b.Cluster.Spec.ExternalDNS == nil || b.Cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderDNSController {
|
||||
{
|
||||
location := key + "/k8s-1.19.yaml"
|
||||
id := "k8s-1.19"
|
||||
key := "dns-controller.addons.k8s.io"
|
||||
location := key + "/k8s-1.12.yaml"
|
||||
id := "k8s-1.12"
|
||||
|
||||
addons.Add(&channelsapi.AddonSpec{
|
||||
Name: fi.String(key),
|
||||
|
@ -521,8 +501,30 @@ func (b *BootstrapChannelBuilder) buildAddons(c *fi.ModelBuilderContext) (*Addon
|
|||
})
|
||||
}
|
||||
|
||||
if b.UseServiceAccountExternalPermissions() {
|
||||
serviceAccountRoles = append(serviceAccountRoles, &externaldns.ServiceAccount{})
|
||||
// Generate dns-controller ServiceAccount IAM permissions.
|
||||
// Gossip clsuters do not require any cloud permissions.
|
||||
if b.UseServiceAccountExternalPermissions() && !b.Cluster.IsGossip() {
|
||||
serviceAccountRoles = append(serviceAccountRoles, &dnscontroller.ServiceAccount{})
|
||||
}
|
||||
} else if b.Cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderExternalDNS {
|
||||
{
|
||||
key := "external-dns.addons.k8s.io"
|
||||
|
||||
{
|
||||
location := key + "/k8s-1.19.yaml"
|
||||
id := "k8s-1.19"
|
||||
|
||||
addons.Add(&channelsapi.AddonSpec{
|
||||
Name: fi.String(key),
|
||||
Selector: map[string]string{"k8s-addon": key},
|
||||
Manifest: fi.String(location),
|
||||
Id: id,
|
||||
})
|
||||
}
|
||||
|
||||
if b.UseServiceAccountExternalPermissions() {
|
||||
serviceAccountRoles = append(serviceAccountRoles, &externaldns.ServiceAccount{})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ func PerformAssignments(c *kops.Cluster, cloud fi.Cloud) error {
|
|||
}
|
||||
|
||||
// TODO: Unclear this should be here - it isn't too hard to change
|
||||
if c.Spec.MasterPublicName == "" && c.ObjectMeta.Name != "" {
|
||||
if c.UsesPublicDNS() && c.Spec.MasterPublicName == "" && c.ObjectMeta.Name != "" {
|
||||
c.Spec.MasterPublicName = "api." + c.ObjectMeta.Name
|
||||
}
|
||||
|
||||
|
|
|
@ -29,8 +29,6 @@ import (
|
|||
"k8s.io/kops/dnsprovider/pkg/dnsprovider/rrstype"
|
||||
"k8s.io/kops/pkg/apis/kops"
|
||||
apimodel "k8s.io/kops/pkg/apis/kops/model"
|
||||
"k8s.io/kops/pkg/model"
|
||||
"k8s.io/kops/pkg/model/iam"
|
||||
"k8s.io/kops/upup/pkg/fi"
|
||||
)
|
||||
|
||||
|
@ -54,6 +52,9 @@ func findZone(cluster *kops.Cluster, cloud fi.Cloud) (dnsprovider.Zone, error) {
|
|||
if err != nil {
|
||||
return nil, fmt.Errorf("error building DNS provider: %v", err)
|
||||
}
|
||||
if dns == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
zonesProvider, ok := dns.Zones()
|
||||
if !ok {
|
||||
|
@ -92,13 +93,8 @@ func findZone(cluster *kops.Cluster, cloud fi.Cloud) (dnsprovider.Zone, error) {
|
|||
}
|
||||
|
||||
func validateDNS(cluster *kops.Cluster, cloud fi.Cloud) error {
|
||||
kopsModelContext := &model.KopsModelContext{
|
||||
IAMModelContext: iam.IAMModelContext{Cluster: cluster},
|
||||
// We are not initializing a lot of the fields here; revisit once UsePrivateDNS is "real"
|
||||
}
|
||||
|
||||
if kopsModelContext.UsePrivateDNS() {
|
||||
klog.V(2).Infof("Private DNS: skipping DNS validation")
|
||||
if cluster.IsGossip() || cluster.UsesPrivateDNS() || cluster.UsesNoneDNS() {
|
||||
klog.V(2).Infof("Skipping DNS validation for non-public DNS")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -106,6 +102,9 @@ func validateDNS(cluster *kops.Cluster, cloud fi.Cloud) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if zone == nil {
|
||||
return nil
|
||||
}
|
||||
dnsName := strings.TrimSuffix(zone.Name(), ".")
|
||||
|
||||
klog.V(2).Infof("Doing DNS lookup to verify NS records for %q", dnsName)
|
||||
|
@ -137,8 +136,8 @@ func precreateDNS(ctx context.Context, cluster *kops.Cluster, cloud fi.Cloud) er
|
|||
// This avoids hitting negative TTL on DNS lookups, which tend to be very long
|
||||
// If we get the names wrong here, it doesn't really matter (extra DNS name, slower boot)
|
||||
|
||||
// Nothing to do for Gossip clusters
|
||||
if cluster.IsGossip() {
|
||||
// Nothing to do for Gossip clusters and clusters without DNS
|
||||
if cluster.IsGossip() || cluster.UsesNoneDNS() {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -153,6 +152,9 @@ func precreateDNS(ctx context.Context, cluster *kops.Cluster, cloud fi.Cloud) er
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if zone == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
rrs, ok := zone.ResourceRecordSets()
|
||||
if !ok {
|
||||
|
@ -219,7 +221,7 @@ func precreateDNS(ctx context.Context, cluster *kops.Cluster, cloud fi.Cloud) er
|
|||
}
|
||||
}
|
||||
if !foundTXT {
|
||||
if cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderExternalDNS {
|
||||
if cluster.Spec.ExternalDNS != nil && cluster.Spec.ExternalDNS.Provider == kops.ExternalDNSProviderExternalDNS {
|
||||
changeset.Add(rrs.New(recordKey.hostname, []string{fmt.Sprintf("\"heritage=external-dns,external-dns/owner=kops-%s\"", cluster.ObjectMeta.Name)}, PlaceholderTTL, rrstype.TXT))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -239,8 +239,8 @@ func (c *hetznerCloudImplementation) GetVolumes(clusterName string) ([]*hcloud.V
|
|||
}
|
||||
|
||||
func (c *hetznerCloudImplementation) DNS() (dnsprovider.Interface, error) {
|
||||
// TODO(hakman): implement me
|
||||
panic("implement me")
|
||||
// Hetzner LB has a stable internal IP and can use that instead of creating a record for api.internal.
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *hetznerCloudImplementation) DeleteInstance(instance *cloudinstances.CloudInstance) error {
|
||||
|
@ -428,14 +428,9 @@ func (c *hetznerCloudImplementation) FindClusterStatus(cluster *kops.Cluster) (*
|
|||
}
|
||||
|
||||
func (c *hetznerCloudImplementation) GetApiIngressStatus(cluster *kops.Cluster) ([]fi.ApiIngressStatus, error) {
|
||||
if cluster.Spec.MasterPublicName == "" {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
lbName := "api." + cluster.Name
|
||||
|
||||
client := c.LoadBalancerClient()
|
||||
// TODO(hakman): Get load balancer info using label selector instead instead of name?
|
||||
lb, _, err := client.GetByName(context.TODO(), lbName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get info for load balancer %q: %w", lbName, err)
|
||||
|
|
|
@ -166,7 +166,6 @@ func (o *NewClusterOptions) InitDefaults() {
|
|||
o.AdminAccess = []string{"0.0.0.0/0", "::/0"}
|
||||
o.Networking = "kubenet"
|
||||
o.Topology = api.TopologyPublic
|
||||
o.DNSType = string(api.DNSTypePublic)
|
||||
o.InstanceManager = "cloudgroups"
|
||||
}
|
||||
|
||||
|
@ -1226,7 +1225,7 @@ func setupTopology(opt *NewClusterOptions, cluster *api.Cluster, allZones sets.S
|
|||
bastionGroup.Spec.MinSize = fi.Int32(1)
|
||||
bastions = append(bastions, bastionGroup)
|
||||
|
||||
if !cluster.IsGossip() {
|
||||
if !cluster.IsGossip() && !cluster.UsesNoneDNS() {
|
||||
cluster.Spec.Topology.Bastion = &api.BastionSpec{
|
||||
PublicName: "bastion." + cluster.Name,
|
||||
}
|
||||
|
@ -1262,10 +1261,20 @@ func setupTopology(opt *NewClusterOptions, cluster *api.Cluster, allZones sets.S
|
|||
|
||||
cluster.Spec.Topology.DNS = &api.DNSSpec{}
|
||||
switch strings.ToLower(opt.DNSType) {
|
||||
case "public", "":
|
||||
case "":
|
||||
if cluster.IsGossip() {
|
||||
cluster.Spec.Topology.DNS.Type = api.DNSTypePrivate
|
||||
} else if cluster.Spec.GetCloudProvider() == api.CloudProviderHetzner {
|
||||
cluster.Spec.Topology.DNS.Type = api.DNSTypeNone
|
||||
} else {
|
||||
cluster.Spec.Topology.DNS.Type = api.DNSTypePublic
|
||||
}
|
||||
case "public":
|
||||
cluster.Spec.Topology.DNS.Type = api.DNSTypePublic
|
||||
case "private":
|
||||
cluster.Spec.Topology.DNS.Type = api.DNSTypePrivate
|
||||
case "none":
|
||||
cluster.Spec.Topology.DNS.Type = api.DNSTypeNone
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown DNSType: %q", opt.DNSType)
|
||||
}
|
||||
|
@ -1290,7 +1299,7 @@ func setupAPI(opt *NewClusterOptions, cluster *api.Cluster) error {
|
|||
} else {
|
||||
switch cluster.Spec.Topology.Masters {
|
||||
case api.TopologyPublic:
|
||||
if cluster.IsGossip() {
|
||||
if cluster.IsGossip() || cluster.UsesNoneDNS() {
|
||||
// gossip DNS names don't work outside the cluster, so we use a LoadBalancer instead
|
||||
cluster.Spec.API.LoadBalancer = &api.LoadBalancerAccessSpec{}
|
||||
} else {
|
||||
|
|
|
@ -219,24 +219,36 @@ func (c *populateClusterSpec) run(clientset simple.Clientset) error {
|
|||
klog.V(2).Infof("Normalizing kubernetes version: %q -> %q", cluster.Spec.KubernetesVersion, versionWithoutV)
|
||||
cluster.Spec.KubernetesVersion = versionWithoutV
|
||||
}
|
||||
if cluster.Spec.DNSZone == "" && !cluster.IsGossip() {
|
||||
if cluster.Spec.DNSZone == "" && !cluster.IsGossip() && !cluster.UsesNoneDNS() {
|
||||
dns, err := cloud.DNS()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dns != nil {
|
||||
dnsType := kopsapi.DNSTypePublic
|
||||
if cluster.Spec.Topology != nil && cluster.Spec.Topology.DNS != nil && cluster.Spec.Topology.DNS.Type != "" {
|
||||
dnsType = cluster.Spec.Topology.DNS.Type
|
||||
}
|
||||
|
||||
dnsType := kopsapi.DNSTypePublic
|
||||
if cluster.Spec.Topology != nil && cluster.Spec.Topology.DNS != nil && cluster.Spec.Topology.DNS.Type != "" {
|
||||
dnsType = cluster.Spec.Topology.DNS.Type
|
||||
dnsZone, err := FindDNSHostedZone(dns, cluster.ObjectMeta.Name, dnsType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error determining default DNS zone: %v", err)
|
||||
}
|
||||
|
||||
klog.V(2).Infof("Defaulting DNS zone to: %s", dnsZone)
|
||||
cluster.Spec.DNSZone = dnsZone
|
||||
}
|
||||
}
|
||||
|
||||
dnsZone, err := FindDNSHostedZone(dns, cluster.ObjectMeta.Name, dnsType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error determining default DNS zone: %v", err)
|
||||
if !cluster.UsesNoneDNS() {
|
||||
if cluster.Spec.DNSZone != "" && cluster.Spec.MasterPublicName == "" {
|
||||
cluster.Spec.MasterPublicName = "api." + cluster.Name
|
||||
}
|
||||
if cluster.Spec.ExternalDNS == nil {
|
||||
cluster.Spec.ExternalDNS = &kopsapi.ExternalDNSConfig{
|
||||
Provider: kopsapi.ExternalDNSProviderDNSController,
|
||||
}
|
||||
}
|
||||
|
||||
klog.V(2).Infof("Defaulting DNS zone to: %s", dnsZone)
|
||||
cluster.Spec.DNSZone = dnsZone
|
||||
}
|
||||
|
||||
if cluster.Spec.KubernetesVersion == "" {
|
||||
|
|
Loading…
Reference in New Issue