kubernetes(3)

news2024/11/20 1:27:29

目录

service微服务

ipvs模式

clusterip

headless

nodeport

loadbalancer

metallb

nodeport默认端口

externalname

ingress-nginx

部署

基于路径访问

基于域名访问

TLS加密

auth认证

rewrite重定向

canary金丝雀发布

基于header灰度

基于权重灰度

业务域拆分


service微服务

创建测试示例

[root@k8s2 service]# vim myapp.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  replicas: 6
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - image: myapp:v1
        name: myapp

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  type: ClusterIP            //ClusterIP是Kubernetes Service的一种类型。它为同一个Kubernetes集群中的其他Pod提供了访问Service的IP地址。这个IP地址和Service是虚拟的, 不对外暴露,只能在集群内部使用。

ClusterIP Service类型默认使用iptables调度。iptables负责将Service的ClusterIP地址映射到后端Pod的IP地址和端口上,处理请求的负载均衡和高可用性

ipvs模式

修改proxy配置

[root@k8s2 pod]# kubectl -n kube-system edit  cm kube-proxy
...
mode: "ipvs"        //IPVS是一种高性能负载均衡技术,与iptables相比具有更高的性能和更丰富的负载均衡策略

重启pod

[root@k8s2 pod]# kubectl -n kube-system get pod|grep kube-proxy | awk '{system("kubectl -n kube-system delete pod "$1"")}'

切换ipvs模式后,kube-proxy会在宿主机上添加一个虚拟网卡:kube-ipvs0,并分配service IP

clusterip

clusterip模式只能在集群内访问

[root@k8s2 service]# vim myapp.yml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  type: ClusterIP

service创建后集群DNS提供解析

headless

[root@k8s2 service]# vim myapp.yml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  type: ClusterIP
  clusterIP: None            //当 ClusterIP 设置为 None 时,Kubernetes 不会为该 Service 分配一个 Cluster IP,并且 DNS 请求的返回值将不会是 Service 的虚拟 IP,而是真实的 Pod IP。

[root@k8s2 service]# kubectl delete svc myapp
[root@k8s2 service]# kubectl apply -f myapp.yml

headless模式不分配vip

headless通过svc名称访问,由集群内dns提供解析

集群内直接使用service名称访问

nodeport

[root@k8s2 service]# vim myapp.yml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  type: NodePort        //NodePort 类型会在每个 Node 上监听一个静态端口,并将请求转发到后端 Pod 的 Cluster IP。这种类型的 Service 可以通过 <NodeIP>:<NodePort> 的方式访问到后端 Pod。
使用 NodePort 类型的 Service 可以让外部用户通过 Node IP 和 Node 端口来访问到集群内部的服务。


[root@k8s2 service]# kubectl apply -f myapp.yml
[root@k8s2 service]# kubectl get svc

nodeport在集群节点上绑定端口,一个端口对应一个服务

loadbalancer

[root@k8s2 service]# vim myapp.yml
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp
  type: LoadBalancer
//使用 LoadBalancer 类型的 Service 可以在集群外部暴露一个负载均衡器,让外部用户能够轻松访问到集群内部的服务。
使用 LoadBalancer 类型的 Service 必须在 Kubernetes 集群部署在某些支持云服务商的基础设施上,否则该类型的 Service 无法正常工作。

LoadBalancer模式适用云平台,裸金属环境需要安装metallb提供支持

metallb

官网:MetalLB, bare metal load-balancer for Kubernetes

[root@k8s2 service]# kubectl edit configmap -n kube-system kube-proxy
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: "ipvs"
ipvs:
  strictARP: true         //启用 Kubernetes Service 的 strictARP 选项可以防止 ARP 欺骗攻击,提高网络安全性

[root@k8s2 service]# kubectl -n kube-system get pod|grep kube-proxy | awk '{system("kubectl -n kube-system delete pod "$1"")}'

 

下载部署文件

[root@k8s2 metallb]# wget https://raw.githubusercontent.com/metallb/metallb/v0.13.11/config/manifests/metallb-native.yaml

修改文件中镜像地址,与harbor仓库路径保持一致

上传镜像到harbor

部署服务

[root@k8s2 metallb]# kubectl apply -f metallb-native.yaml
[root@k8s2 metallb]# kubectl -n metallb-system get pod

配置分段地址段

[root@k8s2 metallb]# vim config.yaml
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: first-pool
  namespace: metallb-system
spec:
  addresses:
  - 192.168.81.100-192.168.81.200			//修改为自己本地地址段

---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: example
  namespace: metallb-system
spec:
  ipAddressPools:
  - first-pool

通过分配地址从集群外访问服务

nodeport默认端口

[root@k8s2 service]# vim myapp.yml

apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp
  name: myapp
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 33333
  selector:
    app: myapp
  type: NodePort

nodeport默认端口是30000-32767,超出会报错

添加如下参数,端口范围可以自定义

[root@k8s2 service]# vim /etc/kubernetes/manifests/kube-apiserver.yaml
--service-node-port- range=30000-50000

修改后api-server会自动重启,等apiserver正常启动后才能操作集群

externalname

[root@k8s2 service]# vim externalname.yaml
apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  type:  ExternalName            //ExternalName 类型的 Service 不会创建任何 ClusterIP、NodePort、LoadBalancer 类型的 Endpoint,在集群内部也不会创建任何 Pod,它会将 Service 名称与一个外部的 DNS 名称(或者 IP 地址)关联起来
  externalName: www.westos.org     //当集群内部的应用程序访问该 Service 时,将会通过集群的 DNS 解析服务解析该 Service 名称,返回关联的 www.westos.org 的 DNS 名称

ingress-nginx

ingress-nginx 是一个 Kubernetes 上的 Ingress 控制器,它提供了负载均衡、SSL/TLS 等功能,可以将外部访问 Kubernetes 集群内部的服务

部署

官网:https://kubernetes.github.io/ingress-nginx/deploy/#bare-metal-clusters

下载部署文件,上传镜像到harbor

修改3个镜像路径

修改为LoadBalancer方式

[root@k8s2 ingress]# kubectl -n ingress-nginx edit  svc ingress-nginx-controller

创建ingress策略

[root@k8s2 ingress]# vim ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp
            port:
              number: 80

基于路径访问

创建svc

[root@k8s2 ingress]# vim myapp-v1.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: myapp-v1
  name: myapp-v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-v1
  template:
    metadata:
      labels:
        app: myapp-v1
    spec:
      containers:
      - image: myapp:v1
        name: myapp-v1

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp-v1
  name: myapp-v1
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp-v1
  type: ClusterIP

[root@k8s2 ingress]# vim myapp-v2.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: myapp-v2
  name: myapp-v2
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp-v2
  template:
    metadata:
      labels:
        app: myapp-v2
    spec:
      containers:
      - image: myapp:v2
        name: myapp-v2

---

apiVersion: v1
kind: Service
metadata:
  labels:
    app: myapp-v2
  name: myapp-v2
spec:
  ports:
  - port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: myapp-v2
  type: ClusterIP

创建ingress

[root@k8s2 ingress]# vim ingress1.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: myapp-v1
            port:
              number: 80

      - path: /v2
        pathType: Prefix
        backend:
          service:
            name: myapp-v2
            port:
              number: 80

测试

基于域名访问

[root@k8s2 ingress]# vim ingress2.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: myapp1.westos.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-v1
            port:
              number: 80

  - host: myapp2.westos.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-v2
            port:
              number: 80

TLS加密

创建证书

[root@k8s2 ingress]# openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj "/CN=nginxsvc/O=nginxsvc"
[root@k8s2 ingress]# kubectl create secret tls tls-secret --key tls.key --cert tls.crt

[root@k8s2 ingress]# vim ingress3.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
spec:
  tls:
    - hosts:
      - myapp.westos.org
      secretName: tls-secret
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-v1
            port:
              number: 80

auth认证

创建认证文件

[root@k8s2 ingress]# yum install -y httpd-tools
[root@k8s2 ingress]# htpasswd -c auth shx
[root@k8s2 ingress]# kubectl create secret generic basic-auth --from-file=auth

[root@k8s2 ingress]# vim ingress3.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - shx'
spec:
  tls:
    - hosts:
      - myapp.westos.org
      secretName: tls-secret
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-v1
            port:
              number: 80

rewrite重定向

示例一:

[root@k8s2 ingress]# vim ingress3.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - shx'
    nginx.ingress.kubernetes.io/app-root: /hostname.html
spec:
  tls:
    - hosts:
      - myapp.westos.org
      secretName: tls-secret
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-v1
            port:
              number: 80

示例二:

[root@k8s2 ingress]# vim ingress3.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-tls
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - shx'
    #nginx.ingress.kubernetes.io/app-root: /hostname.html
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
  tls:
    - hosts:
      - myapp.westos.org
      secretName: tls-secret
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: myapp-v1
            port:
              number: 80
      - path: /westos(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: myapp-v1
            port:
              number: 80

canary金丝雀发布

基于header灰度
[root@k8s2 ingress]# vim ingress4.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-v1-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: myapp-v1
            port:
              number: 80

[root@k8s2 ingress]# vim ingress5.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: stage
    nginx.ingress.kubernetes.io/canary-by-header-value: gray
  name: myapp-v2-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: myapp-v2
            port:
              number: 80

测试

基于权重灰度
[root@k8s2 ingress]# vim ingress5.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    #nginx.ingress.kubernetes.io/canary-by-header: stage
    #nginx.ingress.kubernetes.io/canary-by-header-value: gray
    nginx.ingress.kubernetes.io/canary-weight: "50"
    nginx.ingress.kubernetes.io/canary-weight-total: "100"

  name: myapp-v2-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - pathType: Prefix
        path: /
        backend:
          service:
            name: myapp-v2
            port:
              number: 80

测试

[root@k8s1 ~]# vim ingress.sh
#!/bin/bash

v1=0
v2=0

for (( i=0; i<100; i++))
do
    response=`curl -s myapp.westos.org |grep -c v1`

    v1=`expr $v1 + $response`
    v2=`expr $v2 + 1 - $response`

done

echo "v1:$v1, v2:$v2"

业务域拆分
[root@k8s2 ingress]# vim ingress6.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$1
  name: rewrite-ingress
spec:
  ingressClassName: nginx
  rules:
  - host: myapp.westos.org
    http:
      paths:
      - path: /user/(.*)
        pathType: Prefix
        backend:
          service:
            name: myapp-v1
            port:
              number: 80
      - path: /order/(.*)
        pathType: Prefix
        backend:
          service:
            name: myapp-v2
            port:
              number: 80

测试

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1137986.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【C++】变参函数va_start,va_arg,va_end介绍及实现方式

如果写过JS的话&#xff0c;就知道在JS中定义一个函数&#xff0c;就算输入的实参和形参不一致&#xff0c;也可以同过arguments获取参数 function abc(x) {console.log(x)console.log(arguments[0])console.log(arguments[1])console.log(arguments[2]) } abc(1,2,3)上例输出…

算法通关村第三关-青铜挑战数组专题

本期大纲 线性表基础线性表概念数组概念 数组的基本操作数组创建和初始化查找一个元素增加一个元素修改一个元素删除一个元素 小题一道 - - 单调数组问题小题一道 - - 数组合并问题小结 线性表基础 线性表概念 我们先搞清楚几个基本概念&#xff0c;在很多地方会看到线性结构…

Adversarial attacks and defenses on AI in medical imaging informatics: A survey

Adversarial attacks and defenses on AI in medical imaging informatics: A survey----《AI在医学影像信息学中的对抗性攻击与防御&#xff1a;综述》 背景&#xff1a; 之前的研究表明&#xff0c;人们对医疗DNN及其易受对抗性攻击的脆弱性一直存在疑虑。 摘要&#xff1a;…

实力认可!安全狗入选2023年国产云原生安全技术代表厂商

10月25日&#xff0c;安全牛发布了《2023云原生安全技术应用指南》报告暨年度代表性厂商推荐。 作为国内云原生安全领导厂商&#xff0c;安全狗凭借突出的云原生安全产品与实力成为2023年国产云原生安全技术代表厂商之一。 厦门服云信息科技有限公司&#xff08;品牌名&#xf…

04MQ消息队列

一、同步异步通讯 1.同步通讯和异步通讯 同步通讯&#xff1a;当A服务调用B服务时&#xff0c;一直等待B服务执行完毕&#xff0c;A才继续往下走 优点&#xff1a;时效性强&#xff0c;可以立即得到结果。 缺点&#xff1a; ①耦合度高&#xff0c;加入新的需求就要修改原…

计算机网络【CN】TCP报文段格式【20B】

序号&#xff1a;本报文段所发送的数据的第一个字节的序号确认号&#xff1a;期望收到对方下一个报文段的第一个数据字节的序号。 重要控制位&#xff1a; 紧急位URG&#xff1a;URG1时&#xff0c;标明此报文段中有紧急数据&#xff0c;是高优先级的数据&#xff0c;应尽快传送…

卡巴斯基2009杀毒软件

下载地址&#xff1a;https://user.qzone.qq.com/512526231/main https://user.qzone.qq.com/3503787372/main

冯诺依曼体系结构与操作系统

文章目录 1. 冯诺依曼体系结构概念理解冯诺依曼体系结构的优势 2. 操作系统概念设计OS的目的和定位如何理解管理 1. 冯诺依曼体系结构 概念 我们常见的计算机&#xff0c;如笔记本。我们不常见的计算机&#xff0c;如服务器&#xff0c;大部分都遵守冯诺依曼体系。 对于各个部…

java--跳转关键字和随机数

1.跳转关键字 break&#xff1a;跳出并结束当前所在循环的执行 continue&#xff1a;用于跳出当前循环的当次执行&#xff0c;直接进入循环的下一次执行 2.注意事项 break&#xff1a;只能用于结束所在循环&#xff0c;或结束所在switch语句的执行 continue&#xff1a;只能…

工业交换机常用功能有哪些?

工业交换机&#xff0c;又称工业以太网交换机&#xff0c;是一种在OSI参考模型的第二层&#xff08;数据链路层&#xff09;上工作的网络设备。它基于MAC地址识别&#xff0c;并能够封装和转发数据包。那么&#xff0c;工业交换机的常见常用功能有哪些呢&#xff1f; 工业交换…

JavaWeb——关于servlet种mapping地址映射的一些问题

6、Servlet 6.4、Mapping问题 一个Servlet可以指定一个映射路径 <servlet-mapping><servlet-name>hello</servlet-name><url-pattern>/hello</url-pattern> </servlet-mapping>一个Servlet可以指定多个映射路径 <servlet-mapping>&…

Redis和Memcached网络模型详解

1. Redis单线程单Reactor网络模型 1.1 redis单线程里不能执行十分耗时的流程&#xff0c;不然会客户端响应不及时 解决方法一&#xff1a; beforesleep里删除过期键操作若存在大量过期键时&#xff0c;会耗费大量时间&#xff0c;redis采用的策略之一就是采用timelimit方案超过…

2011-2021年“第四期”数字普惠金融与上市公司匹配(根据城市匹配)/上市公司数字普惠金融指数匹配数据

2011-2021年“第四期”数字普惠金融与上市公司匹配&#xff08;根据城市匹配&#xff09;/上市公司数字普惠金融指数匹配数据 1、时间&#xff1a;2011-2021年 指标&#xff1a;指标&#xff1a;股票代码、年份、行政区划代码、行业名称、行业代码、所属省份、所属城市、数字…

澳大利亚专线的清关时效

随着全球贸易的不断发展&#xff0c;越来越多的企业和个人开始选择通过海运、空运等物流方式将货物运送到世界各地。而在这些运输方式中&#xff0c;澳大利亚专线以其快速、高效的特性受到了广大客户的青睐。本文将为您详细介绍澳大利亚专线的清关时效。 一、澳大利亚专线的定义…

Vben开源添加本地路由(不用显示在菜单的路由)

1.在src\router\routes\modules下创建一个article.ts import type { AppRouteModule } from //router/types;import { LAYOUT } from //router/constant; import { t } from //hooks/web/useI18n;export const article: AppRouteModule {path: /article,name: Article,compon…

疫情集中隔离

系列文章目录 进阶的卡莎C++_睡觉觉觉得的博客-CSDN博客数1的个数_睡觉觉觉得的博客-CSDN博客双精度浮点数的输入输出_睡觉觉觉得的博客-CSDN博客足球联赛积分_睡觉觉觉得的博客-CSDN博客大减价(一级)_睡觉觉觉得的博客-CSDN博客小写字母的判断_睡觉觉觉得的博客-CSDN博客纸币(…

数字人成品牌营销流量密码?看数字人花样赋能品牌

在第十二届李曼中国养猪大会暨世界猪业博览会上&#xff0c;嘉吉动物营养推出了首个数字人产品星推官&#xff0c;在现场数字人结合动捕设备&#xff0c;向观众实时介绍品牌的全明星产品&#xff0c;同时与观众进行实时互动&#xff0c;吸引了众多参展观众的驻足&#xff0c;为…

K8s安装部署-----二进制安装部署

目录 前言 一、操作系统初始化配置 二、部署 etcd 集群 1、在master01节点操作 2、在 node01 节点上操作 3、在 node02 节点上操作 4、查看集群状态 二、部署docker引擎 三、部署 Master 组件 1、准备证书 2、准备二进制文件、token 3、启动kube-apiserver服务 4、…

0基础学习PyFlink——用户自定义函数之UDTF

大纲 表值函数完整代码 在《0基础学习PyFlink——用户自定义函数之UDF》中&#xff0c;我们讲解了UDF。本节我们将讲解表值函数——UDTF 表值函数 我们对比下UDF和UDTF def udf(f: Union[Callable, ScalarFunction, Type] None,input_types: Union[List[DataType], DataTy…

macOS Sonoma 14.1正式版发布 改善Apple Music界面 新增保修状态显示

10月26日消息&#xff0c;苹果今天为 macOS Sonoma 推出了 14.1 版本更新&#xff0c;本更新主要改善了 Apple Music 界面&#xff0c;设置中新增保修状态&#xff0c;并修复了多项错误内容。 经过几周的用户测试&#xff0c;Apple 正式向所有 Mac 用户发布了 macOS Sonoma 14.…