Change:
<!-- Please use this template while reporting a bug and provide as much info as possible. Not doing so may result in your bug not being addressed in a timely manner. Thanks! If the matter is security related, please disclose it privately via --What happened: Duplicate altnames in certs which generated by kubeadm ! What you expected to happen: No Duplicate altnames in certs which generated by kubeadm How to reproduce it (as minimally and precisely as possible): Anytime Anything else we need to know?: ! Environment: Kubernetes version (use ): Cloud provider or hardware configuration: OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others:
/sig cluster-lifecycle
/area kubeadm
Can you describe your detailed usage scenarios and reproduction steps, and explain the kubernetes version so that we can quickly locate
Thank for your response! I have found why and will fix it soon.
i have commented on the PR. /priority awaiting-more-evidence
/remove-priority awaiting-more-evidence /priority backlog

Discussion:
"//cmd/kubeadm/app/constants:go_default_library", "//cmd/kubeadm/app/features:go_default_library", "//cmd/kubeadm/app/util:go_default_library", <ins> "//staging/src/k8s.io/apimachinery/pkg/util/sets:go_default_library", </ins> "//staging/src/k8s.io/apimachinery/pkg/util/validation:go_default_library", "//staging/src/k8s.io/client-go/util/cert:go_default_library", "//staging/src/k8s.io/client-go/util/keyutil:go_default_library",

"github.com/pkg/errors" <ins> "k8s.io/apimachinery/pkg/util/sets" </ins> "k8s.io/apimachinery/pkg/util/validation" certutil "k8s.io/client-go/util/cert" "k8s.io/client-go/util/keyutil"

return nil, errors.New("must specify at least one ExtKeyUsage") } <ins> RemoveDuplicateAltNames(&cfg.AltNames) </ins> certTmpl := x509.Certificate{ Subject: pkix.Name{ CommonName:   cfg.CommonName,

} return x509.ParseCertificate(certDERBytes) } <ins> // RemoveDuplicateAltNames removes duplicate items in altNames. func RemoveDuplicateAltNames(altNames *certutil.AltNames) { if altNames == nil { return } if altNames.DNSNames != nil { altNames.DNSNames = sets.NewString(altNames.DNSNames...).List() } ipsKeys := make(map[string]struct{}) var ips []net.IP for _, one := range altNames.IPs { if _, ok := ipsKeys[one.String()]; !ok { ipsKeys[one.String()] = struct{}{} ips = append(ips, one) } } altNames.IPs = ips } </ins>

"io/ioutil" "net" "os" <ins> "reflect" </ins> "testing" certutil "k8s.io/client-go/util/cert"

} } <ins> func TestRemoveDuplicateAltNames(t *testing.T) { tests := []struct { args *certutil.AltNames want *certutil.AltNames }{ { &certutil.AltNames{}, &certutil.AltNames{}, }, { &certutil.AltNames{ DNSNames: []string{"a", "a"}, IPs:      []net.IP{{127, 0, 0, 1}}, }, &certutil.AltNames{ DNSNames: []string{"a"}, IPs:      []net.IP{{127, 0, 0, 1}}, }, }, { &certutil.AltNames{ DNSNames: []string{"a"}, IPs:      []net.IP{{127, 0, 0, 1}, {127, 0, 0, 1}}, }, &certutil.AltNames{ DNSNames: []string{"a"}, IPs:      []net.IP{{127, 0, 0, 1}}, }, }, { &certutil.AltNames{ DNSNames: []string{"a", "a"}, IPs:      []net.IP{{127, 0, 0, 1}, {127, 0, 0, 1}}, }, &certutil.AltNames{ DNSNames: []string{"a"}, IPs:      []net.IP{{127, 0, 0, 1}}, }, }, } for _, tt := range tests { RemoveDuplicateAltNames(tt.args) if !reflect.DeepEqual(tt.args, tt.want) { t.Errorf("Wanted %v, got %v", tt.want, tt.args) } } } </ins>